<commit_before>#ifndef BLUETOE_BINDINGS_NRF51_HPP
#define BLUETOE_BINDINGS_NRF51_HPP

#include <bluetoe/link_layer/link_layer.hpp>
#include <bluetoe/link_layer/delta_time.hpp>
#include <bluetoe/link_layer/ll_data_pdu_buffer.hpp>
#include <cstdint>

extern "C" void RADIO_IRQHandler(void);
extern "C" void TIMER0_IRQHandler(void);

namespace bluetoe
{
    namespace nrf51_details
    {
        // map compile time callbacks to runtime callbacks for faster development cycles.
        class adv_callbacks
        {
        public:
            virtual void adv_received( const link_layer::read_buffer& receive ) = 0;
            virtual void adv_timeout() = 0;
            virtual void timeout() = 0;
            virtual void end_event() = 0;

            virtual link_layer::write_buffer received_data( const link_layer::read_buffer& ) = 0;
            virtual link_layer::write_buffer next_transmit() = 0;
            virtual link_layer::read_buffer allocate_receive_buffer() = 0;

        };

        class scheduled_radio_base
        {
        public:
            class lock_guard
            {
            public:
                lock_guard();
                ~lock_guard();

                lock_guard( const lock_guard& ) = delete;
                lock_guard& operator=( const lock_guard& ) = delete;
            private:
                const std::uint32_t context_;
            };

            explicit scheduled_radio_base( adv_callbacks& );

            void schedule_advertisment_and_receive(
                unsigned                        channel,
                const link_layer::write_buffer& transmit,
                link_layer::delta_time          when,
                const link_layer::read_buffer&  receive );

            void set_access_address_and_crc_init( std::uint32_t access_address, std::uint32_t crc_init );

            void run();

            void wake_up();

            std::uint32_t static_random_address_seed() const;

        protected:
            void start_connection_event(
                unsigned                        channel,
                bluetoe::link_layer::delta_time start_receive,
                bluetoe::link_layer::delta_time end_receive,
                const link_layer::read_buffer&  receive_buffer );
        private:

            friend void ::RADIO_IRQHandler(void);
            friend void ::TIMER0_IRQHandler(void);

            void adv_radio_interrupt();
            void adv_timer_interrupt();
            void evt_radio_interrupt();
            void evt_timer_interrupt();
            void radio_interrupt();
            void timer_interrupt();

            unsigned frequency_from_channel( unsigned channel ) const;

            adv_callbacks& callbacks_;
            volatile bool timeout_;
            volatile bool received_;
            volatile bool evt_timeout_;
            volatile bool end_evt_;
            volatile int  wake_up_;

            static constexpr unsigned connection_event_type_base = 100;

            enum class state {
                idle,
                // timeout while receiving, stopping the radio, waiting for the radio to become disabled
                adv_timeout_stopping,
                adv_transmitting,
                adv_receiving,
                // connection event
                evt_wait_connect    = connection_event_type_base,
                evt_transmiting_closing,
            };

            volatile state                  state_;

            bluetoe::link_layer::delta_time anchor_offset_;

            link_layer::read_buffer         receive_buffer_;
            std::uint8_t                    empty_receive_[ 2 ];
        };

        template < std::size_t TransmitSize, std::size_t ReceiveSize, typename CallBack >
        class scheduled_radio :
            public bluetoe::link_layer::ll_data_pdu_buffer< TransmitSize, ReceiveSize, scheduled_radio< TransmitSize, ReceiveSize, CallBack > >,
            private adv_callbacks,
            public scheduled_radio_base
        {
        public:
            scheduled_radio() : scheduled_radio_base( static_cast< adv_callbacks& >( *this ) )
            {
            }

            void schedule_connection_event(
                unsigned                                    channel,
                bluetoe::link_layer::delta_time             start_receive,
                bluetoe::link_layer::delta_time             end_receive,
                bluetoe::link_layer::delta_time             connection_interval );

        private:
            using buffer = bluetoe::link_layer::ll_data_pdu_buffer< TransmitSize, ReceiveSize, scheduled_radio< TransmitSize, ReceiveSize, CallBack > >;

            void adv_received( const link_layer::read_buffer& receive ) override
            {
                static_cast< CallBack* >( this )->adv_received( receive );
            }

            void adv_timeout() override
            {
                static_cast< CallBack* >( this )->adv_timeout();
            }

            void timeout() override
            {
                static_cast< CallBack* >( this )->timeout();
            }

            void end_event() override
            {
                static_cast< CallBack* >( this )->end_event();
            }

            link_layer::write_buffer received_data( const link_layer::read_buffer& b ) override
            {
                // this function is called within an ISR context, so no need to disable interrupts
                return this->received( b );
            }

            link_layer::write_buffer next_transmit() override
            {
                // this function is called within an ISR context, so no need to disable interrupts
                return buffer::next_transmit();
            }

            link_layer::read_buffer allocate_receive_buffer() override
            {
                return buffer::allocate_receive_buffer();
            }
        };

        // implementation
        template < std::size_t TransmitSize, std::size_t ReceiveSize, typename CallBack >
        void scheduled_radio< TransmitSize, ReceiveSize, CallBack >::schedule_connection_event(
            unsigned                                    channel,
            bluetoe::link_layer::delta_time             start_receive,
            bluetoe::link_layer::delta_time             end_receive,
            bluetoe::link_layer::delta_time             connection_interval )
        {
            link_layer::read_buffer read;
            {
                lock_guard lock;
                read = buffer::allocate_receive_buffer();
            }

            start_connection_event( channel, start_receive, end_receive, read );
        }
    }

    template < class Server, typename ... Options >
    using nrf51 = link_layer::link_layer< Server, nrf51_details::scheduled_radio, Options... >;
}

#endif // include guard
<commit_msg>no hardware support for WL<commit_after>#ifndef BLUETOE_BINDINGS_NRF51_HPP
#define BLUETOE_BINDINGS_NRF51_HPP

#include <bluetoe/link_layer/link_layer.hpp>
#include <bluetoe/link_layer/delta_time.hpp>
#include <bluetoe/link_layer/ll_data_pdu_buffer.hpp>
#include <cstdint>

extern "C" void RADIO_IRQHandler(void);
extern "C" void TIMER0_IRQHandler(void);

namespace bluetoe
{
    namespace nrf51_details
    {
        // map compile time callbacks to runtime callbacks for faster development cycles.
        class adv_callbacks
        {
        public:
            virtual void adv_received( const link_layer::read_buffer& receive ) = 0;
            virtual void adv_timeout() = 0;
            virtual void timeout() = 0;
            virtual void end_event() = 0;

            virtual link_layer::write_buffer received_data( const link_layer::read_buffer& ) = 0;
            virtual link_layer::write_buffer next_transmit() = 0;
            virtual link_layer::read_buffer allocate_receive_buffer() = 0;

        };

        class scheduled_radio_base
        {
        public:
            class lock_guard
            {
            public:
                lock_guard();
                ~lock_guard();

                lock_guard( const lock_guard& ) = delete;
                lock_guard& operator=( const lock_guard& ) = delete;
            private:
                const std::uint32_t context_;
            };

            explicit scheduled_radio_base( adv_callbacks& );

            void schedule_advertisment_and_receive(
                unsigned                        channel,
                const link_layer::write_buffer& transmit,
                link_layer::delta_time          when,
                const link_layer::read_buffer&  receive );

            void set_access_address_and_crc_init( std::uint32_t access_address, std::uint32_t crc_init );

            void run();

            void wake_up();

            std::uint32_t static_random_address_seed() const;

            // no native white list implementation atm
            static constexpr std::size_t radio_maximum_white_list_entries = 0;
        protected:
            void start_connection_event(
                unsigned                        channel,
                bluetoe::link_layer::delta_time start_receive,
                bluetoe::link_layer::delta_time end_receive,
                const link_layer::read_buffer&  receive_buffer );
        private:

            friend void ::RADIO_IRQHandler(void);
            friend void ::TIMER0_IRQHandler(void);

            void adv_radio_interrupt();
            void adv_timer_interrupt();
            void evt_radio_interrupt();
            void evt_timer_interrupt();
            void radio_interrupt();
            void timer_interrupt();

            unsigned frequency_from_channel( unsigned channel ) const;

            adv_callbacks& callbacks_;
            volatile bool timeout_;
            volatile bool received_;
            volatile bool evt_timeout_;
            volatile bool end_evt_;
            volatile int  wake_up_;

            static constexpr unsigned connection_event_type_base = 100;

            enum class state {
                idle,
                // timeout while receiving, stopping the radio, waiting for the radio to become disabled
                adv_timeout_stopping,
                adv_transmitting,
                adv_receiving,
                // connection event
                evt_wait_connect    = connection_event_type_base,
                evt_transmiting_closing,
            };

            volatile state                  state_;

            bluetoe::link_layer::delta_time anchor_offset_;

            link_layer::read_buffer         receive_buffer_;
            std::uint8_t                    empty_receive_[ 2 ];
        };

        template < std::size_t TransmitSize, std::size_t ReceiveSize, typename CallBack >
        class scheduled_radio :
            public bluetoe::link_layer::ll_data_pdu_buffer< TransmitSize, ReceiveSize, scheduled_radio< TransmitSize, ReceiveSize, CallBack > >,
            private adv_callbacks,
            public scheduled_radio_base
        {
        public:
            scheduled_radio() : scheduled_radio_base( static_cast< adv_callbacks& >( *this ) )
            {
            }

            void schedule_connection_event(
                unsigned                                    channel,
                bluetoe::link_layer::delta_time             start_receive,
                bluetoe::link_layer::delta_time             end_receive,
                bluetoe::link_layer::delta_time             connection_interval );

        private:
            using buffer = bluetoe::link_layer::ll_data_pdu_buffer< TransmitSize, ReceiveSize, scheduled_radio< TransmitSize, ReceiveSize, CallBack > >;

            void adv_received( const link_layer::read_buffer& receive ) override
            {
                static_cast< CallBack* >( this )->adv_received( receive );
            }

            void adv_timeout() override
            {
                static_cast< CallBack* >( this )->adv_timeout();
            }

            void timeout() override
            {
                static_cast< CallBack* >( this )->timeout();
            }

            void end_event() override
            {
                static_cast< CallBack* >( this )->end_event();
            }

            link_layer::write_buffer received_data( const link_layer::read_buffer& b ) override
            {
                // this function is called within an ISR context, so no need to disable interrupts
                return this->received( b );
            }

            link_layer::write_buffer next_transmit() override
            {
                // this function is called within an ISR context, so no need to disable interrupts
                return buffer::next_transmit();
            }

            link_layer::read_buffer allocate_receive_buffer() override
            {
                return buffer::allocate_receive_buffer();
            }
        };

        // implementation
        template < std::size_t TransmitSize, std::size_t ReceiveSize, typename CallBack >
        void scheduled_radio< TransmitSize, ReceiveSize, CallBack >::schedule_connection_event(
            unsigned                                    channel,
            bluetoe::link_layer::delta_time             start_receive,
            bluetoe::link_layer::delta_time             end_receive,
            bluetoe::link_layer::delta_time             connection_interval )
        {
            link_layer::read_buffer read;
            {
                lock_guard lock;
                read = buffer::allocate_receive_buffer();
            }

            start_connection_event( channel, start_receive, end_receive, read );
        }
    }

    template < class Server, typename ... Options >
    using nrf51 = link_layer::link_layer< Server, nrf51_details::scheduled_radio, Options... >;
}

#endif // include guard
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_3DCanvasSource.h"

#include "EC_3DCanvas.h"
#include "EC_Mesh.h"
#include "EC_OgreCustomObject.h"
#include "IModule.h"
#include "ModuleManager.h"
#include "Entity.h"
#include "UiProxyWidget.h"
#include "UiServiceInterface.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_3DCanvasSource")

#include <QWebView>
#include <QLineEdit>
#include <QApplication>
#include <QPushButton>
#include <QUiLoader>
#include <QVBoxLayout>

#include "MemoryLeakCheck.h"

EC_3DCanvasSource::EC_3DCanvasSource(IModule *module) :
    IComponent(module->GetFramework()),
    source(this, "source"),
    position(this, "position", 0),
    submesh(this, "submesh", 0),
    show2d(this, "show 2D", true),
    widget_(0),
    content_widget_(0),
    placeholder_widget_(0),
    proxy_(0),
    source_edit_(0),
    manipulate_ec_3dcanvas(true)
{
    connect(this, SIGNAL(OnAttributeChanged(IAttribute*, AttributeChange::Type)), this, SLOT(UpdateWidgetAndCanvas()));
    connect(this, SIGNAL(ParentEntitySet()), this, SLOT(RegisterActions()));
    CreateWidget();
}

EC_3DCanvasSource::~EC_3DCanvasSource()
{
    // Note: content widget is inside widget_s layout,
    // no need to do a separate deleteLater for it. This would cause problems on rundown.
    SAFE_DELETE_LATER(widget_);
}

void EC_3DCanvasSource::OnClick()
{
    if ((getshow2d() == true) && (widget_) && (proxy_))
    {
        if (proxy_->isVisible())
            proxy_->AnimatedHide();
        else
            proxy_->show();
    }
}

void EC_3DCanvasSource::SourceEdited()
{
    QString new_source = source_edit_->text();
    if (new_source != getsource())
    {
        // Replicate changed source to network
        // std::cout << "Changed source to " << new_source << std::endl;
        setsource(new_source);
        ComponentChanged(AttributeChange::Default);
    }
}

void EC_3DCanvasSource::StartPressed()
{
}

void EC_3DCanvasSource::PrevPressed()
{
}

void EC_3DCanvasSource::NextPressed()
{
}

void EC_3DCanvasSource::EndPressed()
{
}

void EC_3DCanvasSource::UpdateWidgetAndCanvas()
{
    UpdateWidget();
    UpdateCanvas();
}

void EC_3DCanvasSource::WebViewLinkClicked(const QUrl& url)
{
    //! \todo: check here if the link is something we want to open differently (external program etc.)

    // If url is different than the source, update the lineedit & browser & replicate to network
    QString url_str = url.toString();
    if (url_str != getsource())
    {
        QWebView* webwidget = dynamic_cast<QWebView*>(content_widget_);
        if (!webwidget)
            return;
        webwidget->setUrl(url);

        if (source_edit_)
            source_edit_->setText(url_str);

        // Set last_source now so that we won't trigger reload of the page again when the source comes back from network
        last_source_ = url_str;

        // std::cout << "Changed source by click to " << url_str << std::endl;
        setsource(url_str);
        ComponentChanged(AttributeChange::Default);
    }
}

void EC_3DCanvasSource::RepaintCanvas()
{
    if (!manipulate_ec_3dcanvas)
        return;

    Scene::Entity* entity = GetParentEntity();
    if (!entity)
        return;

    ComponentPtr comp = entity->GetComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
        return;

    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    canvas->Start();
}

void EC_3DCanvasSource::UpdateWidget()
{
    QString source = getsource();
    if (source.isEmpty())
    {
        QTimer::singleShot(1000, this, SLOT(FetchWebViewUrl()));
        return;
    }

    if (source != last_source_)
    {
        if (source_edit_)
            source_edit_->setText(source);

        last_source_ = source;
        if (!placeholder_widget_)
        {
            LogError("No placeholder widget, cannot create content widget");
            return;
        }

        // See if source looks like an url, and instantiate a QWebView then if it doesn't already exist
        if (source.indexOf("http://") != -1)
        {
            QWebView* webwidget = dynamic_cast<QWebView*>(content_widget_);
            if (!webwidget)
            {
                // If widget exists, but is wrong type, delete and recreate
                if (content_widget_)
                {
                    content_widget_->deleteLater();
                    content_widget_ = 0;
                }

                webwidget = new QWebView(placeholder_widget_);
                QVBoxLayout *layout = placeholder_widget_->findChild<QVBoxLayout*>("widget_placeholder_layout");
                if (layout)
                    layout->addWidget(webwidget);

                webwidget->setUrl(QUrl(source));
                webwidget->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
                content_widget_ = webwidget;

                connect(webwidget, SIGNAL(loadFinished( bool )), this, SLOT(RepaintCanvas()));
                connect(webwidget, SIGNAL(loadProgress( int )), this, SLOT(RepaintCanvas()));
                connect(webwidget, SIGNAL(linkClicked( const QUrl & )), this, SLOT(WebViewLinkClicked( const QUrl & )));
                connect(webwidget->page(), SIGNAL(scrollRequested( int, int, const QRect & )), this, SLOT(RepaintCanvas()));
            }
            else
            {
                // If source changed, update the webview URL
                webwidget->setUrl(QUrl(source));
            }
        }
    }
}

void EC_3DCanvasSource::UpdateCanvas()
{
    if (!content_widget_ || !manipulate_ec_3dcanvas)
        return;

    Scene::Entity* entity = GetParentEntity();
    if (!entity)
    {
        LogError("No parent entity, cannot create/update 3DCanvas");
        return;
    }

    ComponentPtr comp = entity->GetOrCreateComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
    {
        LogError("Could not create/get 3DCanvas component");
        return;
    }

    // If entity has no valid mesh or prim yet, start a retry timer and try to set the canvas later
    if ((!entity->GetComponent(EC_Mesh::TypeNameStatic())) &&
        (!entity->GetComponent(EC_OgreCustomObject::TypeNameStatic())))
    {
        //LogInfo("Mesh or prim did not exist yet, retrying");
        QTimer::singleShot(1000, this, SLOT(UpdateCanvas()));
        return;
    }

    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    canvas->SetWidget(content_widget_);
    int submesh = getsubmesh();
    if (submesh < 0)
        submesh = 0;
    canvas->SetSubmesh(submesh);
    canvas->Start();
}

void EC_3DCanvasSource::FetchWebViewUrl()
{
    // Workaround on the bug that ec_3canvas->webview()->url() is not valid when this component is created/updated.
    // Somehow its doesent have time to set it before we already come here. So this polls untill the url is valid.

    Scene::Entity* entity = GetParentEntity();
    if (!entity)
    {
        LogError("No parent entity, cannot create/update 3DCanvas");
        return;
    }

    ComponentPtr comp = entity->GetOrCreateComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
    {
        LogError("Could not create/get 3DCanvas component");
        return;
    }

    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    QWidget *canvas_widget = canvas->GetWidget();
    if (!canvas_widget)
        return;
    QWebView *canvas_webview = dynamic_cast<QWebView*>(canvas_widget);
    if (!canvas_webview)
        return;
    QString url = canvas_webview->url().toString();
    if (!url.isEmpty())
    {
        setsource(url);
        ComponentChanged(AttributeChange::LocalOnly);
    }
    else
        QTimer::singleShot(1000, this, SLOT(FetchWebViewUrl()));
}

void EC_3DCanvasSource::ChangeLanguage()
{
    if (widget_)
    {
        QString title = tr("3DCanvas Controls");
        widget_->setWindowTitle(title);
    }
}

void EC_3DCanvasSource::CreateWidget()
{
    UiServiceInterface *ui = framework_->GetService<UiServiceInterface>();
    if (!ui)
    {
        LogError("Failed to acquire UI service");
        return;
    }

    QUiLoader loader;
    loader.setLanguageChangeEnabled(true);
    QFile file("./data/ui/3dcanvassource.ui");
    file.open(QFile::ReadOnly);
    widget_ = loader.load(&file);
    file.close();

    if (!widget_)
    {
        LogError("Failed to create 3D canvas controls widget");
        return;
    }

    widget_->setWindowTitle(tr("3DCanvas Controls"));
    proxy_ = ui->AddWidgetToScene(widget_);

    connect(qApp, SIGNAL(LanguageChanged()), this, SLOT(ChangeLanguage()));

    source_edit_ = widget_->findChild<QLineEdit*>("line_source");
    if (source_edit_)
    {
        connect(source_edit_, SIGNAL( editingFinished() ), this, SLOT( SourceEdited() ));
    }

    placeholder_widget_ = widget_->findChild<QWidget*>("widget_placeholder");

    QPushButton* button = widget_->findChild<QPushButton*>("but_start");
    if (button) connect(button, SIGNAL( clicked() ), this, SLOT( StartPressed() ));
    button = widget_->findChild<QPushButton*>("but_prev");
    if (button) connect(button, SIGNAL( clicked() ), this, SLOT( PrevPressed() ));
    button = widget_->findChild<QPushButton*>("but_next");
    if (button) connect(button, SIGNAL( clicked() ), this, SLOT( NextPressed() ));
    button = widget_->findChild<QPushButton*>("but_end");
    if (button) connect(button, SIGNAL( clicked() ), this, SLOT( EndPressed() ));
}

void EC_3DCanvasSource::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
        entity->ConnectAction("MousePress", this, SLOT(OnClick()));
}

<commit_msg>3D webview 2D widget wont show on click events if its scene is not active. So now it does not try to show when you click on entities in build mode that have the 3D webview<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_3DCanvasSource.h"

#include "EC_3DCanvas.h"
#include "EC_Mesh.h"
#include "EC_OgreCustomObject.h"
#include "IModule.h"
#include "ModuleManager.h"
#include "Entity.h"
#include "UiProxyWidget.h"
#include "UiServiceInterface.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_3DCanvasSource")

#include <QWebView>
#include <QLineEdit>
#include <QApplication>
#include <QPushButton>
#include <QUiLoader>
#include <QVBoxLayout>
#include <QGraphicsScene>

#include "MemoryLeakCheck.h"

EC_3DCanvasSource::EC_3DCanvasSource(IModule *module) :
    IComponent(module->GetFramework()),
    source(this, "source"),
    position(this, "position", 0),
    submesh(this, "submesh", 0),
    show2d(this, "show 2D", true),
    widget_(0),
    content_widget_(0),
    placeholder_widget_(0),
    proxy_(0),
    source_edit_(0),
    manipulate_ec_3dcanvas(true)
{
    connect(this, SIGNAL(OnAttributeChanged(IAttribute*, AttributeChange::Type)), this, SLOT(UpdateWidgetAndCanvas()));
    connect(this, SIGNAL(ParentEntitySet()), this, SLOT(RegisterActions()));
    CreateWidget();
}

EC_3DCanvasSource::~EC_3DCanvasSource()
{
    // Note: content widget is inside widget_s layout,
    // no need to do a separate deleteLater for it. This would cause problems on rundown.
    SAFE_DELETE_LATER(widget_);
}

void EC_3DCanvasSource::OnClick()
{
    if ((getshow2d() == true) && (widget_) && (proxy_))
    {
        if (!proxy_->scene())
            return;
        if (!proxy_->scene()->isActive())
            return;
        if (proxy_->isVisible())
            proxy_->AnimatedHide();
        else
            proxy_->show();
    }
}

void EC_3DCanvasSource::SourceEdited()
{
    QString new_source = source_edit_->text();
    if (new_source != getsource())
    {
        // Replicate changed source to network
        // std::cout << "Changed source to " << new_source << std::endl;
        setsource(new_source);
        ComponentChanged(AttributeChange::Default);
    }
}

void EC_3DCanvasSource::StartPressed()
{
}

void EC_3DCanvasSource::PrevPressed()
{
}

void EC_3DCanvasSource::NextPressed()
{
}

void EC_3DCanvasSource::EndPressed()
{
}

void EC_3DCanvasSource::UpdateWidgetAndCanvas()
{
    UpdateWidget();
    UpdateCanvas();
}

void EC_3DCanvasSource::WebViewLinkClicked(const QUrl& url)
{
    //! \todo: check here if the link is something we want to open differently (external program etc.)

    // If url is different than the source, update the lineedit & browser & replicate to network
    QString url_str = url.toString();
    if (url_str != getsource())
    {
        QWebView* webwidget = dynamic_cast<QWebView*>(content_widget_);
        if (!webwidget)
            return;
        webwidget->setUrl(url);

        if (source_edit_)
            source_edit_->setText(url_str);

        // Set last_source now so that we won't trigger reload of the page again when the source comes back from network
        last_source_ = url_str;

        // std::cout << "Changed source by click to " << url_str << std::endl;
        setsource(url_str);
        ComponentChanged(AttributeChange::Default);
    }
}

void EC_3DCanvasSource::RepaintCanvas()
{
    if (!manipulate_ec_3dcanvas)
        return;

    Scene::Entity* entity = GetParentEntity();
    if (!entity)
        return;

    ComponentPtr comp = entity->GetComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
        return;

    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    canvas->Start();
}

void EC_3DCanvasSource::UpdateWidget()
{
    QString source = getsource();
    if (source.isEmpty())
    {
        QTimer::singleShot(1000, this, SLOT(FetchWebViewUrl()));
        return;
    }

    if (source != last_source_)
    {
        if (source_edit_)
            source_edit_->setText(source);

        last_source_ = source;
        if (!placeholder_widget_)
        {
            LogError("No placeholder widget, cannot create content widget");
            return;
        }

        // See if source looks like an url, and instantiate a QWebView then if it doesn't already exist
        if (source.indexOf("http://") != -1)
        {
            QWebView* webwidget = dynamic_cast<QWebView*>(content_widget_);
            if (!webwidget)
            {
                // If widget exists, but is wrong type, delete and recreate
                if (content_widget_)
                {
                    content_widget_->deleteLater();
                    content_widget_ = 0;
                }

                webwidget = new QWebView(placeholder_widget_);
                QVBoxLayout *layout = placeholder_widget_->findChild<QVBoxLayout*>("widget_placeholder_layout");
                if (layout)
                    layout->addWidget(webwidget);

                webwidget->setUrl(QUrl(source));
                webwidget->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
                content_widget_ = webwidget;

                connect(webwidget, SIGNAL(loadFinished( bool )), this, SLOT(RepaintCanvas()));
                connect(webwidget, SIGNAL(loadProgress( int )), this, SLOT(RepaintCanvas()));
                connect(webwidget, SIGNAL(linkClicked( const QUrl & )), this, SLOT(WebViewLinkClicked( const QUrl & )));
                connect(webwidget->page(), SIGNAL(scrollRequested( int, int, const QRect & )), this, SLOT(RepaintCanvas()));
            }
            else
            {
                // If source changed, update the webview URL
                webwidget->setUrl(QUrl(source));
            }
        }
    }
}

void EC_3DCanvasSource::UpdateCanvas()
{
    if (!content_widget_ || !manipulate_ec_3dcanvas)
        return;

    Scene::Entity* entity = GetParentEntity();
    if (!entity)
    {
        LogError("No parent entity, cannot create/update 3DCanvas");
        return;
    }

    ComponentPtr comp = entity->GetOrCreateComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
    {
        LogError("Could not create/get 3DCanvas component");
        return;
    }

    // If entity has no valid mesh or prim yet, start a retry timer and try to set the canvas later
    if ((!entity->GetComponent(EC_Mesh::TypeNameStatic())) &&
        (!entity->GetComponent(EC_OgreCustomObject::TypeNameStatic())))
    {
        //LogInfo("Mesh or prim did not exist yet, retrying");
        QTimer::singleShot(1000, this, SLOT(UpdateCanvas()));
        return;
    }

    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    canvas->SetWidget(content_widget_);
    int submesh = getsubmesh();
    if (submesh < 0)
        submesh = 0;
    canvas->SetSubmesh(submesh);
    canvas->Start();
}

void EC_3DCanvasSource::FetchWebViewUrl()
{
    // Workaround on the bug that ec_3canvas->webview()->url() is not valid when this component is created/updated.
    // Somehow its doesent have time to set it before we already come here. So this polls untill the url is valid.

    Scene::Entity* entity = GetParentEntity();
    if (!entity)
    {
        LogError("No parent entity, cannot create/update 3DCanvas");
        return;
    }

    ComponentPtr comp = entity->GetOrCreateComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
    {
        LogError("Could not create/get 3DCanvas component");
        return;
    }

    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    QWidget *canvas_widget = canvas->GetWidget();
    if (!canvas_widget)
        return;
    QWebView *canvas_webview = dynamic_cast<QWebView*>(canvas_widget);
    if (!canvas_webview)
        return;
    QString url = canvas_webview->url().toString();
    if (!url.isEmpty())
    {
        setsource(url);
        ComponentChanged(AttributeChange::LocalOnly);
    }
    else
        QTimer::singleShot(1000, this, SLOT(FetchWebViewUrl()));
}

void EC_3DCanvasSource::ChangeLanguage()
{
    if (widget_)
    {
        QString title = tr("3DCanvas Controls");
        widget_->setWindowTitle(title);
    }
}

void EC_3DCanvasSource::CreateWidget()
{
    UiServiceInterface *ui = framework_->GetService<UiServiceInterface>();
    if (!ui)
    {
        LogError("Failed to acquire UI service");
        return;
    }

    QUiLoader loader;
    loader.setLanguageChangeEnabled(true);
    QFile file("./data/ui/3dcanvassource.ui");
    file.open(QFile::ReadOnly);
    widget_ = loader.load(&file);
    file.close();

    if (!widget_)
    {
        LogError("Failed to create 3D canvas controls widget");
        return;
    }

    widget_->setWindowTitle(tr("3DCanvas Controls"));
    proxy_ = ui->AddWidgetToScene(widget_);

    connect(qApp, SIGNAL(LanguageChanged()), this, SLOT(ChangeLanguage()));

    source_edit_ = widget_->findChild<QLineEdit*>("line_source");
    if (source_edit_)
    {
        connect(source_edit_, SIGNAL( editingFinished() ), this, SLOT( SourceEdited() ));
    }

    placeholder_widget_ = widget_->findChild<QWidget*>("widget_placeholder");

    QPushButton* button = widget_->findChild<QPushButton*>("but_start");
    if (button) connect(button, SIGNAL( clicked() ), this, SLOT( StartPressed() ));
    button = widget_->findChild<QPushButton*>("but_prev");
    if (button) connect(button, SIGNAL( clicked() ), this, SLOT( PrevPressed() ));
    button = widget_->findChild<QPushButton*>("but_next");
    if (button) connect(button, SIGNAL( clicked() ), this, SLOT( NextPressed() ));
    button = widget_->findChild<QPushButton*>("but_end");
    if (button) connect(button, SIGNAL( clicked() ), this, SLOT( EndPressed() ));
}

void EC_3DCanvasSource::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
        entity->ConnectAction("MousePress", this, SLOT(OnClick()));
}

<|endoftext|>


<commit_before>/**
 * @file
 *      exercise_03_23.cpp
 * @author
 *      Henrik Samuelsson, henrik.samuelsson(at)gmail.com
 */
#include <iostream>
#include <vector>

using std::cout;
using std::vector;

int main() {
    vector<int> i_vec{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    // Assign each element a value that is twice its current value.
    for (auto it = i_vec.begin(); it != i_vec.end(); ++it) {
        *it = 2 * *it;
    }

    // Print the vector to verify the functionality of the program.
     for (auto it = i_vec.begin(); it != i_vec.end(); ++it) {
        cout << *it << " ";
    }
}
<commit_msg>Update exercise_03_23.cpp<commit_after>/**
 * @file
 *      exercise_03_23.cpp
 * @author
 *      Henrik Samuelsson, henrik.samuelsson(at)gmail.com
 */
#include <iostream>
#include <vector>

using std::cout;
using std::vector;

int main() {
    vector<int> i_vec{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    // Assign each element in the vector a value that is twice its current value.
    for (auto it = i_vec.begin(); it != i_vec.end(); ++it) {
        *it = 2 * *it;
    }

    // Print the vector to verify the functionality of the program.
     for (auto it = i_vec.begin(); it != i_vec.end(); ++it) {
        cout << *it << " ";
    }
}
<|endoftext|>


<commit_before>/**
 * @file
 *      exercise_11_03.cpp
 * @author
 *      Henrik Samuelsson, henrik.samuelsson(at)gmail.com
 */
#include <map>
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::map;
using std::string;

int main() {
    map<string, size_t> word_count; // Empty map from string to size_t.
    string word;

    // Get input words from the user of the program.
    while (cin >> word) {
        ++word_count[word];    // Fetch and increment the counter for word.
    }

    // Print the result of the word count.
    for (const auto &w : word_count) {  // For each element in word count.
        cout << w.first << " occurs " << w.second
                << ((w.second < 1) ? " times" : " time") << endl;
    }
    return 0;
}
<commit_msg>Update exercise_11_03.cpp<commit_after>/**
 * @file
 *      exercise_11_03.cpp
 * @author
 *      Henrik Samuelsson, henrik.samuelsson(at)gmail.com
 */
#include <map>
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::map;
using std::string;

int main() {
    map<string, size_t> word_count; // Empty map from string to size_t.
    string word;

    // Get input words from the user of the program.
    while (cin >> word) {
        ++word_count[word];    // Fetch and increment the counter for word.
    }

    // Print the result of the word count.
    for (const auto &w : word_count) {  // For each element in word count.
        cout << w.first << " occurs " << w.second
                << ((w.second < 1) ? " times" : " time") << endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>AliAnalysisTaskDiMuonCorrelations *AddAnalysisTaskDiMuonCorrelations(const char *centMethod = "V0M") {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    printf("Error in adding AnalysisTaskDiMuonCorrelations: no Analysis Manager found!\n");
    return NULL;
  }

  AliAnalysisTaskDiMuonCorrelations *task = new AliAnalysisTaskDiMuonCorrelations(Form("AliAnalysisTaskDiMuonCorrelations_%s",centMethod));

  // Set analysis cuts
  task->SetLikeSign(kTRUE);
  task->SetEtaRangeMuon(-4.0, -2.5);
  task->SetTriggerMatchLevelMuon(1);

  const Int_t nBinCent = 4;
  Double_t centLimits[nBinCent+1] = {0., 20., 40, 60., 100.};
  task->SetCentBinning(nBinCent, centLimits);

  task->SetCentMethod(centMethod);

  const Int_t nBinPt = 3;
  Double_t ptLimits[nBinPt+1] = {0., 1., 2., 4.};
  task->SetPtBinning(nBinPt, ptLimits);

  const Int_t nBinEta = 3;
  Double_t etaLimits[nBinEta+1] = {-4., -3.6, -3.2, -2.5};
  task->SetEtaBinning(nBinEta, etaLimits);

  mgr->AddTask(task);

  // create output container
  AliAnalysisDataContainer *output = mgr->CreateContainer(Form("DiMuonCorrHistos_%s",centMethod), TList::Class(), AliAnalysisManager::kOutputContainer,
							  Form("%s:DiMuonCorrelations_%s", AliAnalysisManager::GetCommonFileName(), centMethod));

  // finaly connect input and output
  mgr->ConnectInput(task, 0,  mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, output);

  return task;
}

<commit_msg>Add macro updated<commit_after>AliAnalysisTaskDiMuonCorrelations *AddAnalysisTaskDiMuonCorrelations(const char *centMethod = "V0A", Bool_t likeSign = kTRUE) {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    printf("Error in adding AnalysisTaskDiMuonCorrelations: no Analysis Manager found!\n");
    return NULL;
  }

  AliAnalysisTaskDiMuonCorrelations *task = new AliAnalysisTaskDiMuonCorrelations(Form("AliAnalysisTaskDiMuonCorrelations_%s",centMethod));

  // Set analysis cuts
  task->SetLikeSign(likeSign);
  task->SetEtaRangeMuon(-4.0, -2.5);
  task->SetTriggerMatchLevelMuon(1);

  const Int_t nBinCent = 4;
  Double_t centLimits[nBinCent+1] = {0., 20., 40, 60., 100.};
  task->SetCentBinning(nBinCent, centLimits);

  task->SetCentMethod(centMethod);

  const Int_t nBinPt = 3;
  Double_t ptLimits[nBinPt+1] = {0., 1., 2., 4.};
  task->SetPtBinning(nBinPt, ptLimits);

  const Int_t nBinEta = 3;
  Double_t etaLimits[nBinEta+1] = {-4., -3.6, -3.2, -2.5};
  task->SetEtaBinning(nBinEta, etaLimits);

  mgr->AddTask(task);

  // create output container
  AliAnalysisDataContainer *output = mgr->CreateContainer(Form("DiMuonCorrHistos_%s",centMethod), TList::Class(), AliAnalysisManager::kOutputContainer,
							  Form("%s:DiMuonCorrelations_%s", AliAnalysisManager::GetCommonFileName(), centMethod));

  // finaly connect input and output
  mgr->ConnectInput(task, 0,  mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, output);

  return task;
}

<|endoftext|>


<commit_before>#include "Decoder_LDPC_BP_peeling.hpp"

#include "Tools/Perf/common/hard_decide.h"
#include "Tools/Noise/Erased_value.hpp"
#include "Tools/Math/utils.h"

using namespace aff3ct;
using namespace aff3ct::module;

template<typename B, typename R>
Decoder_LDPC_BP_peeling<B, R>::Decoder_LDPC_BP_peeling(const int K, const int N, const int n_ite,
                                                       const tools::Sparse_matrix &H,
                                                       const std::vector<unsigned> &info_bits_pos,
                                                       const bool enable_syndrome, const int syndrome_depth,
                                                       const int n_frames)
: Decoder                (K, N,                                            n_frames, 1),
  Decoder_LDPC_BP<B,R>   (K, N, n_ite, H, enable_syndrome, syndrome_depth, n_frames, 1),
  info_bits_pos          (info_bits_pos                                               ),
  var_nodes              (n_frames, std::vector<B>(N             )                    ),
  check_nodes            (n_frames, std::vector<B>(H.get_n_cols())                    )
{
	const std::string name = "Decoder_LDPC_BP_peeling";
	this->set_name(name);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_load(const R *Y_N, const int frame_id)
{
	tools::hard_decide(Y_N, var_nodes[frame_id].data(), this->N);
	for (auto i = 0; i < this->N; i++)
		if (Y_N[i] <= tools::Erased_value<R>::llr && Y_N[i] >= -tools::Erased_value<R>::llr)
			var_nodes[frame_id][i] = tools::Erased_value<B>::symbol;
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode(const int frame_id)
{
	auto links = this->H;

	std::fill(this->check_nodes[frame_id].begin(), this->check_nodes[frame_id].end(), (B)0);

	// std::cout << "(L) var_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
	// 	std::cout << this->var_nodes[frame_id][i] << " ";
	// std::cout << std::endl;
	// std::cout << "(L) check_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
	// 	std::cout << this->check_nodes[frame_id][i] << " ";
	// std::cout << std::endl;

	// std::cout << "(L) links : " << std::endl;
	// links.print(true);

	// first propagate known values
	for (unsigned i = 0; i < links.get_n_rows(); i++)
	{
		auto cur_state = this->var_nodes[frame_id][i];
		if (cur_state != tools::Erased_value<B>::symbol)
		{
			auto& cn_list = links.get_row_to_cols()[i];
			while (cn_list.size())
			{
				auto& cn_pos = cn_list.front();

				this->check_nodes[frame_id][cn_pos] ^= cur_state;
				links.rm_connection(i, cn_pos);
			}
		}
	}

	// std::cout << "(I) var_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
	// 	std::cout << this->var_nodes[frame_id][i] << " ";
	// std::cout << std::endl;
	// std::cout << "(I) check_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
	// 	std::cout << this->check_nodes[frame_id][i] << " ";
	// std::cout << std::endl;

	// std::cout << "(I) links : " << std::endl;
	// links.print(true);

	for (auto ite = 0; ite < this->n_ite; ite++)
	{
		bool all_check_nodes_done = true, no_modification = true;

		// find degree-1 check nodes
		for (unsigned i = 0; i < links.get_n_cols(); i++)
		{
			if (links.get_col_to_rows()[i].size() == 1)
			{ // then propagate the belief
				auto& vn_pos = links.get_col_to_rows()[i].front();
				this->var_nodes  [frame_id][vn_pos] = this->check_nodes[frame_id][i];
				this->check_nodes[frame_id][     i] = 0;
				links.rm_connection(vn_pos, i);
				no_modification = false;
			}
			else
				all_check_nodes_done &= links.get_col_to_rows()[i].size() == 0;
		}

		// std::cout << "(" << ite << ") var_nodes : " << std::endl;
		// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
		// 	std::cout << this->var_nodes[frame_id][i] << " ";
		// std::cout << std::endl;
		// std::cout << "(" << ite << ") check_nodes : " << std::endl;
		// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
		// 	std::cout << this->check_nodes[frame_id][i] << " ";
		// std::cout << std::endl;

		if (this->enable_syndrome && (all_check_nodes_done || no_modification))
		{
			this->cur_syndrome_depth++;
			if (this->cur_syndrome_depth == this->syndrome_depth)
				break;
		}
		else
			this->cur_syndrome_depth = 0;
	}
};

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_hiho(const B *Y_N, B *V_K, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	std::copy(Y_N, Y_N + this->N, var_nodes[frame_id].data());
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store(V_K, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_hiho].update_timer(dec::tm::decode_hiho::decode, d_decod);
//	(*this)[dec::tsk::decode_hiho].update_timer(dec::tm::decode_hiho::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_hiho_cw(const B *Y_N, B *V_N, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	std::copy(Y_N, Y_N + this->N, var_nodes[frame_id].data());
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store_cw(V_N, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_hiho_cw].update_timer(dec::tm::decode_hiho_cw::decode, d_decod);
//	(*this)[dec::tsk::decode_hiho_cw].update_timer(dec::tm::decode_hiho_cw::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_siho(const R *Y_N, B *V_K, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	this->_load(Y_N, frame_id);
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store(V_K, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::load,   d_load);
//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::decode, d_decod);
//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_siho_cw(const R *Y_N, B *V_N, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	this->_load(Y_N, frame_id);
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store_cw(V_N, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::load,   d_load);
//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::decode, d_decod);
//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::store,  d_store);
}

template<typename B, typename R>
void Decoder_LDPC_BP_peeling<B, R>::_store(B *V_K, const int frame_id)
{
	for (auto i = 0; i < this->K; i++)
		V_K[i] = this->var_nodes[frame_id][this->info_bits_pos[i]];
}

template<typename B, typename R>
void Decoder_LDPC_BP_peeling<B, R>::_store_cw(B *V_N, const int frame_id)
{
	std::copy(this->var_nodes[frame_id].begin(), this->var_nodes[frame_id].end(), V_N);
}

// ==================================================================================== explicit template instantiation
#include "Tools/types.h"
#ifdef MULTI_PREC
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_8,Q_8>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_16,Q_16>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_32,Q_32>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_64,Q_64>;
#else
template class aff3ct::module::Decoder_LDPC_BP_peeling<B,Q>;
#endif
// ==================================================================================== explicit template instantiation
<commit_msg>Use Sparse_matrix::get_cols_from_row method to be more clear<commit_after>#include "Decoder_LDPC_BP_peeling.hpp"

#include "Tools/Perf/common/hard_decide.h"
#include "Tools/Noise/Erased_value.hpp"
#include "Tools/Math/utils.h"

using namespace aff3ct;
using namespace aff3ct::module;

template<typename B, typename R>
Decoder_LDPC_BP_peeling<B, R>::Decoder_LDPC_BP_peeling(const int K, const int N, const int n_ite,
                                                       const tools::Sparse_matrix &_H,
                                                       const std::vector<unsigned> &info_bits_pos,
                                                       const bool enable_syndrome, const int syndrome_depth,
                                                       const int n_frames)
: Decoder                (K, N,                                             n_frames, 1),
  Decoder_LDPC_BP<B,R>   (K, N, n_ite, _H, enable_syndrome, syndrome_depth, n_frames, 1),
  info_bits_pos          (info_bits_pos                                                ),
  var_nodes              (n_frames, std::vector<B>(N                   )               ),
  check_nodes            (n_frames, std::vector<B>(this->H.get_n_cols())               )
{
	const std::string name = "Decoder_LDPC_BP_peeling";
	this->set_name(name);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_load(const R *Y_N, const int frame_id)
{
	tools::hard_decide(Y_N, var_nodes[frame_id].data(), this->N);
	for (auto i = 0; i < this->N; i++)
		if (Y_N[i] <= tools::Erased_value<R>::llr && Y_N[i] >= -tools::Erased_value<R>::llr)
			var_nodes[frame_id][i] = tools::Erased_value<B>::symbol;
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode(const int frame_id)
{
	auto links = this->H;

	std::fill(this->check_nodes[frame_id].begin(), this->check_nodes[frame_id].end(), (B)0);

	// std::cout << "(L) var_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
	// 	std::cout << this->var_nodes[frame_id][i] << " ";
	// std::cout << std::endl;
	// std::cout << "(L) check_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
	// 	std::cout << this->check_nodes[frame_id][i] << " ";
	// std::cout << std::endl;

	// std::cout << "(L) links : " << std::endl;
	// links.print(true);

	// first propagate known values
	for (unsigned i = 0; i < links.get_n_rows(); i++)
	{
		auto cur_state = this->var_nodes[frame_id][i];
		if (cur_state != tools::Erased_value<B>::symbol)
		{
			auto& cn_list = links.get_cols_from_row(i);
			while (cn_list.size())
			{
				auto& cn_pos = cn_list.front();

				this->check_nodes[frame_id][cn_pos] ^= cur_state;
				links.rm_connection(i, cn_pos);
			}
		}
	}

	// std::cout << "(I) var_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
	// 	std::cout << this->var_nodes[frame_id][i] << " ";
	// std::cout << std::endl;
	// std::cout << "(I) check_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
	// 	std::cout << this->check_nodes[frame_id][i] << " ";
	// std::cout << std::endl;

	// std::cout << "(I) links : " << std::endl;
	// links.print(true);

	for (auto ite = 0; ite < this->n_ite; ite++)
	{
		bool all_check_nodes_done = true, no_modification = true;

		// find degree-1 check nodes
		for (unsigned i = 0; i < links.get_n_cols(); i++)
		{
			if (links.get_col_to_rows()[i].size() == 1)
			{ // then propagate the belief
				auto& vn_pos = links.get_rows_from_col(i).front();
				this->var_nodes  [frame_id][vn_pos] = this->check_nodes[frame_id][i];
				this->check_nodes[frame_id][     i] = 0;
				links.rm_connection(vn_pos, i);
				no_modification = false;
			}
			else
				all_check_nodes_done &= links.get_rows_from_col(i).size() == 0;
		}

		// std::cout << "(" << ite << ") var_nodes : " << std::endl;
		// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
		// 	std::cout << this->var_nodes[frame_id][i] << " ";
		// std::cout << std::endl;
		// std::cout << "(" << ite << ") check_nodes : " << std::endl;
		// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
		// 	std::cout << this->check_nodes[frame_id][i] << " ";
		// std::cout << std::endl;

		if (this->enable_syndrome && (all_check_nodes_done || no_modification))
		{
			this->cur_syndrome_depth++;
			if (this->cur_syndrome_depth == this->syndrome_depth)
				break;
		}
		else
			this->cur_syndrome_depth = 0;
	}
};

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_hiho(const B *Y_N, B *V_K, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	std::copy(Y_N, Y_N + this->N, var_nodes[frame_id].data());
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store(V_K, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_hiho].update_timer(dec::tm::decode_hiho::decode, d_decod);
//	(*this)[dec::tsk::decode_hiho].update_timer(dec::tm::decode_hiho::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_hiho_cw(const B *Y_N, B *V_N, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	std::copy(Y_N, Y_N + this->N, var_nodes[frame_id].data());
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store_cw(V_N, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_hiho_cw].update_timer(dec::tm::decode_hiho_cw::decode, d_decod);
//	(*this)[dec::tsk::decode_hiho_cw].update_timer(dec::tm::decode_hiho_cw::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_siho(const R *Y_N, B *V_K, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	this->_load(Y_N, frame_id);
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store(V_K, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::load,   d_load);
//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::decode, d_decod);
//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_siho_cw(const R *Y_N, B *V_N, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	this->_load(Y_N, frame_id);
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store_cw(V_N, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::load,   d_load);
//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::decode, d_decod);
//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::store,  d_store);
}

template<typename B, typename R>
void Decoder_LDPC_BP_peeling<B, R>::_store(B *V_K, const int frame_id)
{
	for (auto i = 0; i < this->K; i++)
		V_K[i] = this->var_nodes[frame_id][this->info_bits_pos[i]];
}

template<typename B, typename R>
void Decoder_LDPC_BP_peeling<B, R>::_store_cw(B *V_N, const int frame_id)
{
	std::copy(this->var_nodes[frame_id].begin(), this->var_nodes[frame_id].end(), V_N);
}

// ==================================================================================== explicit template instantiation
#include "Tools/types.h"
#ifdef MULTI_PREC
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_8,Q_8>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_16,Q_16>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_32,Q_32>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_64,Q_64>;
#else
template class aff3ct::module::Decoder_LDPC_BP_peeling<B,Q>;
#endif
// ==================================================================================== explicit template instantiation
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif

#include "chainparamsbase.h"
#include "clientversion.h"
#include "rpc/client.h"
#include "rpc/protocol.h"
#include "util.h"
#include "utilstrencodings.h"

#include <boost/filesystem/operations.hpp>
#include <stdio.h>

#include <event2/buffer.h>
#include <event2/keyvalq_struct.h>
#include "support/events.h"

#include <univalue.h>

static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
static const bool DEFAULT_NAMED=false;
static const int CONTINUE_EXECUTION=-1;

std::string HelpMessageCli()
{
    std::string strUsage;
    strUsage += HelpMessageGroup(_("Options:"));
    strUsage += HelpMessageOpt("-?", _("This help message"));
    strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME));
    strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
    AppendParamsHelpMessages(strUsage);
    strUsage += HelpMessageOpt("-named", strprintf(_("Pass named instead of positional arguments (default: %s)"), DEFAULT_NAMED));
    strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), DEFAULT_RPCCONNECT));
    strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), BaseParams(CBaseChainParams::MAIN).RPCPort(), BaseParams(CBaseChainParams::TESTNET).RPCPort()));
    strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
    strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
    strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
    strUsage += HelpMessageOpt("-rpcclienttimeout=<n>", strprintf(_("Timeout during HTTP requests (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT));
    strUsage += HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases)"));

    return strUsage;
}

//////////////////////////////////////////////////////////////////////////////
//
// Start
//

//
// Exception thrown on connection error.  This error is used to determine
// when to wait if -rpcwait is given.
//
class CConnectionFailed : public std::runtime_error
{
public:

    explicit inline CConnectionFailed(const std::string& msg) :
        std::runtime_error(msg)
    {}

};

//
// This function returns either one of EXIT_ codes when it's expected to stop the process or
// CONTINUE_EXECUTION when it's expected to continue further.
//
static int AppInitRPC(int argc, char* argv[])
{
    //
    // Parameters
    //
    ParseParameters(argc, argv);
    if (argc<2 || IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help") || IsArgSet("-version")) {
        std::string strUsage = strprintf(_("%s RPC client version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n";
        if (!IsArgSet("-version")) {
            strUsage += "\n" + _("Usage:") + "\n" +
                  "  bitcoin-cli [options] <command> [params]  " + strprintf(_("Send command to %s"), _(PACKAGE_NAME)) + "\n" +
                  "  bitcoin-cli [options] -named <command> [name=value] ... " + strprintf(_("Send command to %s (with named arguments)"), _(PACKAGE_NAME)) + "\n" +
                  "  bitcoin-cli [options] help                " + _("List commands") + "\n" +
                  "  bitcoin-cli [options] help <command>      " + _("Get help for a command") + "\n";

            strUsage += "\n" + HelpMessageCli();
        }

        fprintf(stdout, "%s", strUsage.c_str());
        if (argc < 2) {
            fprintf(stderr, "Error: too few parameters\n");
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;
    }
    if (!boost::filesystem::is_directory(GetDataDir(false))) {
        fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str());
        return EXIT_FAILURE;
    }
    try {
        ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME));
    } catch (const std::exception& e) {
        fprintf(stderr,"Error reading configuration file: %s\n", e.what());
        return EXIT_FAILURE;
    }
    // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
    try {
        SelectBaseParams(ChainNameFromCommandLine());
    } catch (const std::exception& e) {
        fprintf(stderr, "Error: %s\n", e.what());
        return EXIT_FAILURE;
    }
    if (GetBoolArg("-rpcssl", false))
    {
        fprintf(stderr, "Error: SSL mode for RPC (-rpcssl) is no longer supported.\n");
        return EXIT_FAILURE;
    }
    return CONTINUE_EXECUTION;
}

/** Reply structure for request_done to fill in */
struct HTTPReply
{
    HTTPReply(): status(0), error(-1) {}

    int status;
    int error;
    std::string body;
};

const char *http_errorstring(int code)
{
    switch(code) {
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
    case EVREQ_HTTP_TIMEOUT:
        return "timeout reached";
    case EVREQ_HTTP_EOF:
        return "EOF reached";
    case EVREQ_HTTP_INVALID_HEADER:
        return "error while reading header, or invalid header";
    case EVREQ_HTTP_BUFFER_ERROR:
        return "error encountered while reading or writing";
    case EVREQ_HTTP_REQUEST_CANCEL:
        return "request was canceled";
    case EVREQ_HTTP_DATA_TOO_LONG:
        return "response body is larger than allowed";
#endif
    default:
        return "unknown";
    }
}

static void http_request_done(struct evhttp_request *req, void *ctx)
{
    HTTPReply *reply = static_cast<HTTPReply*>(ctx);

    if (req == NULL) {
        /* If req is NULL, it means an error occurred while connecting: the
         * error code will have been passed to http_error_cb.
         */
        reply->status = 0;
        return;
    }

    reply->status = evhttp_request_get_response_code(req);

    struct evbuffer *buf = evhttp_request_get_input_buffer(req);
    if (buf)
    {
        size_t size = evbuffer_get_length(buf);
        const char *data = (const char*)evbuffer_pullup(buf, size);
        if (data)
            reply->body = std::string(data, size);
        evbuffer_drain(buf, size);
    }
}

#if LIBEVENT_VERSION_NUMBER >= 0x02010300
static void http_error_cb(enum evhttp_request_error err, void *ctx)
{
    HTTPReply *reply = static_cast<HTTPReply*>(ctx);
    reply->error = err;
}
#endif

UniValue CallRPC(const std::string& strMethod, const UniValue& params)
{
    std::string host = GetArg("-rpcconnect", DEFAULT_RPCCONNECT);
    int port = GetArg("-rpcport", BaseParams().RPCPort());

    // Obtain event base
    raii_event_base base = obtain_event_base();

    // Synchronously look up hostname
    raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port);
    evhttp_connection_set_timeout(evcon.get(), GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));

    HTTPReply response;
    raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response);
    if (req == NULL)
        throw std::runtime_error("create http request failed");
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
    evhttp_request_set_error_cb(req.get(), http_error_cb);
#endif

    // Get credentials
    std::string strRPCUserColonPass;
    if (GetArg("-rpcpassword", "") == "") {
        // Try fall back to cookie-based authentication if no password is provided
        if (!GetAuthCookie(&strRPCUserColonPass)) {
            throw std::runtime_error(strprintf(
                _("Could not locate RPC credentials. No authentication cookie could be found, and no rpcpassword is set in the configuration file (%s)"),
                    GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string().c_str()));

        }
    } else {
        strRPCUserColonPass = GetArg("-rpcuser", "") + ":" + GetArg("-rpcpassword", "");
    }

    struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get());
    assert(output_headers);
    evhttp_add_header(output_headers, "Host", host.c_str());
    evhttp_add_header(output_headers, "Connection", "close");
    evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str());

    // Attach request data
    std::string strRequest = JSONRPCRequestObj(strMethod, params, 1).write() + "\n";
    struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get());
    assert(output_buffer);
    evbuffer_add(output_buffer, strRequest.data(), strRequest.size());

    int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, "/");
    req.release(); // ownership moved to evcon in above call
    if (r != 0) {
        throw CConnectionFailed("send http request failed");
    }

    event_base_dispatch(base.get());

    if (response.status == 0)
        throw CConnectionFailed(strprintf("couldn't connect to server: %s (code %d)\n(make sure server is running and you are connecting to the correct RPC port)", http_errorstring(response.error), response.error));
    else if (response.status == HTTP_UNAUTHORIZED)
        throw std::runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
    else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
        throw std::runtime_error(strprintf("server returned HTTP error %d", response.status));
    else if (response.body.empty())
        throw std::runtime_error("no response from server");

    // Parse reply
    UniValue valReply(UniValue::VSTR);
    if (!valReply.read(response.body))
        throw std::runtime_error("couldn't parse reply from server");
    const UniValue& reply = valReply.get_obj();
    if (reply.empty())
        throw std::runtime_error("expected reply to have result, error and id properties");

    return reply;
}

int CommandLineRPC(int argc, char *argv[])
{
    std::string strPrint;
    int nRet = 0;
    try {
        // Skip switches
        while (argc > 1 && IsSwitchChar(argv[1][0])) {
            argc--;
            argv++;
        }
        std::vector<std::string> args = std::vector<std::string>(&argv[1], &argv[argc]);
        if (GetBoolArg("-stdin", false)) {
            // Read one arg per line from stdin and append
            std::string line;
            while (std::getline(std::cin,line))
                args.push_back(line);
        }
        if (args.size() < 1)
            throw std::runtime_error("too few parameters (need at least command)");
        std::string strMethod = args[0];
        args.erase(args.begin()); // Remove trailing method name from arguments vector

        UniValue params;
        if(GetBoolArg("-named", DEFAULT_NAMED)) {
            params = RPCConvertNamedValues(strMethod, args);
        } else {
            params = RPCConvertValues(strMethod, args);
        }

        // Execute and handle connection failures with -rpcwait
        const bool fWait = GetBoolArg("-rpcwait", false);
        do {
            try {
                const UniValue reply = CallRPC(strMethod, params);

                // Parse reply
                const UniValue& result = find_value(reply, "result");
                const UniValue& error  = find_value(reply, "error");

                if (!error.isNull()) {
                    // Error
                    int code = error["code"].get_int();
                    if (fWait && code == RPC_IN_WARMUP)
                        throw CConnectionFailed("server in warmup");
                    strPrint = "error: " + error.write();
                    nRet = abs(code);
                    if (error.isObject())
                    {
                        UniValue errCode = find_value(error, "code");
                        UniValue errMsg  = find_value(error, "message");
                        strPrint = errCode.isNull() ? "" : "error code: "+errCode.getValStr()+"\n";

                        if (errMsg.isStr())
                            strPrint += "error message:\n"+errMsg.get_str();
                    }
                } else {
                    // Result
                    if (result.isNull())
                        strPrint = "";
                    else if (result.isStr())
                        strPrint = result.get_str();
                    else
                        strPrint = result.write(2);
                }
                // Connection succeeded, no need to retry.
                break;
            }
            catch (const CConnectionFailed&) {
                if (fWait)
                    MilliSleep(1000);
                else
                    throw;
            }
        } while (fWait);
    }
    catch (const boost::thread_interrupted&) {
        throw;
    }
    catch (const std::exception& e) {
        strPrint = std::string("error: ") + e.what();
        nRet = EXIT_FAILURE;
    }
    catch (...) {
        PrintExceptionContinue(NULL, "CommandLineRPC()");
        throw;
    }

    if (strPrint != "") {
        fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
    }
    return nRet;
}

int main(int argc, char* argv[])
{
    SetupEnvironment();
    if (!SetupNetworking()) {
        fprintf(stderr, "Error: Initializing networking failed\n");
        return EXIT_FAILURE;
    }

    try {
        int ret = AppInitRPC(argc, argv);
        if (ret != CONTINUE_EXECUTION)
            return ret;
    }
    catch (const std::exception& e) {
        PrintExceptionContinue(&e, "AppInitRPC()");
        return EXIT_FAILURE;
    } catch (...) {
        PrintExceptionContinue(NULL, "AppInitRPC()");
        return EXIT_FAILURE;
    }

    int ret = EXIT_FAILURE;
    try {
        ret = CommandLineRPC(argc, argv);
    }
    catch (const std::exception& e) {
        PrintExceptionContinue(&e, "CommandLineRPC()");
    } catch (...) {
        PrintExceptionContinue(NULL, "CommandLineRPC()");
    }
    return ret;
}
<commit_msg>Docs: add details to -rpcclienttimeout doc<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif

#include "chainparamsbase.h"
#include "clientversion.h"
#include "rpc/client.h"
#include "rpc/protocol.h"
#include "util.h"
#include "utilstrencodings.h"

#include <boost/filesystem/operations.hpp>
#include <stdio.h>

#include <event2/buffer.h>
#include <event2/keyvalq_struct.h>
#include "support/events.h"

#include <univalue.h>

static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
static const bool DEFAULT_NAMED=false;
static const int CONTINUE_EXECUTION=-1;

std::string HelpMessageCli()
{
    std::string strUsage;
    strUsage += HelpMessageGroup(_("Options:"));
    strUsage += HelpMessageOpt("-?", _("This help message"));
    strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME));
    strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
    AppendParamsHelpMessages(strUsage);
    strUsage += HelpMessageOpt("-named", strprintf(_("Pass named instead of positional arguments (default: %s)"), DEFAULT_NAMED));
    strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), DEFAULT_RPCCONNECT));
    strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), BaseParams(CBaseChainParams::MAIN).RPCPort(), BaseParams(CBaseChainParams::TESTNET).RPCPort()));
    strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
    strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
    strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
    strUsage += HelpMessageOpt("-rpcclienttimeout=<n>", strprintf(_("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT));
    strUsage += HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases)"));

    return strUsage;
}

//////////////////////////////////////////////////////////////////////////////
//
// Start
//

//
// Exception thrown on connection error.  This error is used to determine
// when to wait if -rpcwait is given.
//
class CConnectionFailed : public std::runtime_error
{
public:

    explicit inline CConnectionFailed(const std::string& msg) :
        std::runtime_error(msg)
    {}

};

//
// This function returns either one of EXIT_ codes when it's expected to stop the process or
// CONTINUE_EXECUTION when it's expected to continue further.
//
static int AppInitRPC(int argc, char* argv[])
{
    //
    // Parameters
    //
    ParseParameters(argc, argv);
    if (argc<2 || IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help") || IsArgSet("-version")) {
        std::string strUsage = strprintf(_("%s RPC client version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n";
        if (!IsArgSet("-version")) {
            strUsage += "\n" + _("Usage:") + "\n" +
                  "  bitcoin-cli [options] <command> [params]  " + strprintf(_("Send command to %s"), _(PACKAGE_NAME)) + "\n" +
                  "  bitcoin-cli [options] -named <command> [name=value] ... " + strprintf(_("Send command to %s (with named arguments)"), _(PACKAGE_NAME)) + "\n" +
                  "  bitcoin-cli [options] help                " + _("List commands") + "\n" +
                  "  bitcoin-cli [options] help <command>      " + _("Get help for a command") + "\n";

            strUsage += "\n" + HelpMessageCli();
        }

        fprintf(stdout, "%s", strUsage.c_str());
        if (argc < 2) {
            fprintf(stderr, "Error: too few parameters\n");
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;
    }
    if (!boost::filesystem::is_directory(GetDataDir(false))) {
        fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str());
        return EXIT_FAILURE;
    }
    try {
        ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME));
    } catch (const std::exception& e) {
        fprintf(stderr,"Error reading configuration file: %s\n", e.what());
        return EXIT_FAILURE;
    }
    // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
    try {
        SelectBaseParams(ChainNameFromCommandLine());
    } catch (const std::exception& e) {
        fprintf(stderr, "Error: %s\n", e.what());
        return EXIT_FAILURE;
    }
    if (GetBoolArg("-rpcssl", false))
    {
        fprintf(stderr, "Error: SSL mode for RPC (-rpcssl) is no longer supported.\n");
        return EXIT_FAILURE;
    }
    return CONTINUE_EXECUTION;
}

/** Reply structure for request_done to fill in */
struct HTTPReply
{
    HTTPReply(): status(0), error(-1) {}

    int status;
    int error;
    std::string body;
};

const char *http_errorstring(int code)
{
    switch(code) {
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
    case EVREQ_HTTP_TIMEOUT:
        return "timeout reached";
    case EVREQ_HTTP_EOF:
        return "EOF reached";
    case EVREQ_HTTP_INVALID_HEADER:
        return "error while reading header, or invalid header";
    case EVREQ_HTTP_BUFFER_ERROR:
        return "error encountered while reading or writing";
    case EVREQ_HTTP_REQUEST_CANCEL:
        return "request was canceled";
    case EVREQ_HTTP_DATA_TOO_LONG:
        return "response body is larger than allowed";
#endif
    default:
        return "unknown";
    }
}

static void http_request_done(struct evhttp_request *req, void *ctx)
{
    HTTPReply *reply = static_cast<HTTPReply*>(ctx);

    if (req == NULL) {
        /* If req is NULL, it means an error occurred while connecting: the
         * error code will have been passed to http_error_cb.
         */
        reply->status = 0;
        return;
    }

    reply->status = evhttp_request_get_response_code(req);

    struct evbuffer *buf = evhttp_request_get_input_buffer(req);
    if (buf)
    {
        size_t size = evbuffer_get_length(buf);
        const char *data = (const char*)evbuffer_pullup(buf, size);
        if (data)
            reply->body = std::string(data, size);
        evbuffer_drain(buf, size);
    }
}

#if LIBEVENT_VERSION_NUMBER >= 0x02010300
static void http_error_cb(enum evhttp_request_error err, void *ctx)
{
    HTTPReply *reply = static_cast<HTTPReply*>(ctx);
    reply->error = err;
}
#endif

UniValue CallRPC(const std::string& strMethod, const UniValue& params)
{
    std::string host = GetArg("-rpcconnect", DEFAULT_RPCCONNECT);
    int port = GetArg("-rpcport", BaseParams().RPCPort());

    // Obtain event base
    raii_event_base base = obtain_event_base();

    // Synchronously look up hostname
    raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port);
    evhttp_connection_set_timeout(evcon.get(), GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));

    HTTPReply response;
    raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response);
    if (req == NULL)
        throw std::runtime_error("create http request failed");
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
    evhttp_request_set_error_cb(req.get(), http_error_cb);
#endif

    // Get credentials
    std::string strRPCUserColonPass;
    if (GetArg("-rpcpassword", "") == "") {
        // Try fall back to cookie-based authentication if no password is provided
        if (!GetAuthCookie(&strRPCUserColonPass)) {
            throw std::runtime_error(strprintf(
                _("Could not locate RPC credentials. No authentication cookie could be found, and no rpcpassword is set in the configuration file (%s)"),
                    GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string().c_str()));

        }
    } else {
        strRPCUserColonPass = GetArg("-rpcuser", "") + ":" + GetArg("-rpcpassword", "");
    }

    struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get());
    assert(output_headers);
    evhttp_add_header(output_headers, "Host", host.c_str());
    evhttp_add_header(output_headers, "Connection", "close");
    evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str());

    // Attach request data
    std::string strRequest = JSONRPCRequestObj(strMethod, params, 1).write() + "\n";
    struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get());
    assert(output_buffer);
    evbuffer_add(output_buffer, strRequest.data(), strRequest.size());

    int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, "/");
    req.release(); // ownership moved to evcon in above call
    if (r != 0) {
        throw CConnectionFailed("send http request failed");
    }

    event_base_dispatch(base.get());

    if (response.status == 0)
        throw CConnectionFailed(strprintf("couldn't connect to server: %s (code %d)\n(make sure server is running and you are connecting to the correct RPC port)", http_errorstring(response.error), response.error));
    else if (response.status == HTTP_UNAUTHORIZED)
        throw std::runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
    else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
        throw std::runtime_error(strprintf("server returned HTTP error %d", response.status));
    else if (response.body.empty())
        throw std::runtime_error("no response from server");

    // Parse reply
    UniValue valReply(UniValue::VSTR);
    if (!valReply.read(response.body))
        throw std::runtime_error("couldn't parse reply from server");
    const UniValue& reply = valReply.get_obj();
    if (reply.empty())
        throw std::runtime_error("expected reply to have result, error and id properties");

    return reply;
}

int CommandLineRPC(int argc, char *argv[])
{
    std::string strPrint;
    int nRet = 0;
    try {
        // Skip switches
        while (argc > 1 && IsSwitchChar(argv[1][0])) {
            argc--;
            argv++;
        }
        std::vector<std::string> args = std::vector<std::string>(&argv[1], &argv[argc]);
        if (GetBoolArg("-stdin", false)) {
            // Read one arg per line from stdin and append
            std::string line;
            while (std::getline(std::cin,line))
                args.push_back(line);
        }
        if (args.size() < 1)
            throw std::runtime_error("too few parameters (need at least command)");
        std::string strMethod = args[0];
        args.erase(args.begin()); // Remove trailing method name from arguments vector

        UniValue params;
        if(GetBoolArg("-named", DEFAULT_NAMED)) {
            params = RPCConvertNamedValues(strMethod, args);
        } else {
            params = RPCConvertValues(strMethod, args);
        }

        // Execute and handle connection failures with -rpcwait
        const bool fWait = GetBoolArg("-rpcwait", false);
        do {
            try {
                const UniValue reply = CallRPC(strMethod, params);

                // Parse reply
                const UniValue& result = find_value(reply, "result");
                const UniValue& error  = find_value(reply, "error");

                if (!error.isNull()) {
                    // Error
                    int code = error["code"].get_int();
                    if (fWait && code == RPC_IN_WARMUP)
                        throw CConnectionFailed("server in warmup");
                    strPrint = "error: " + error.write();
                    nRet = abs(code);
                    if (error.isObject())
                    {
                        UniValue errCode = find_value(error, "code");
                        UniValue errMsg  = find_value(error, "message");
                        strPrint = errCode.isNull() ? "" : "error code: "+errCode.getValStr()+"\n";

                        if (errMsg.isStr())
                            strPrint += "error message:\n"+errMsg.get_str();
                    }
                } else {
                    // Result
                    if (result.isNull())
                        strPrint = "";
                    else if (result.isStr())
                        strPrint = result.get_str();
                    else
                        strPrint = result.write(2);
                }
                // Connection succeeded, no need to retry.
                break;
            }
            catch (const CConnectionFailed&) {
                if (fWait)
                    MilliSleep(1000);
                else
                    throw;
            }
        } while (fWait);
    }
    catch (const boost::thread_interrupted&) {
        throw;
    }
    catch (const std::exception& e) {
        strPrint = std::string("error: ") + e.what();
        nRet = EXIT_FAILURE;
    }
    catch (...) {
        PrintExceptionContinue(NULL, "CommandLineRPC()");
        throw;
    }

    if (strPrint != "") {
        fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
    }
    return nRet;
}

int main(int argc, char* argv[])
{
    SetupEnvironment();
    if (!SetupNetworking()) {
        fprintf(stderr, "Error: Initializing networking failed\n");
        return EXIT_FAILURE;
    }

    try {
        int ret = AppInitRPC(argc, argv);
        if (ret != CONTINUE_EXECUTION)
            return ret;
    }
    catch (const std::exception& e) {
        PrintExceptionContinue(&e, "AppInitRPC()");
        return EXIT_FAILURE;
    } catch (...) {
        PrintExceptionContinue(NULL, "AppInitRPC()");
        return EXIT_FAILURE;
    }

    int ret = EXIT_FAILURE;
    try {
        ret = CommandLineRPC(argc, argv);
    }
    catch (const std::exception& e) {
        PrintExceptionContinue(&e, "CommandLineRPC()");
    } catch (...) {
        PrintExceptionContinue(NULL, "CommandLineRPC()");
    }
    return ret;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:set ts=4 sw=4 sts=4 noet: */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "exec/job-runner.hh"

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <future>
#include <thread>

#define BOOST_FILESYSTEM_NO_DEPRECATED
#include <boost/filesystem.hpp>

#include "compiler.hh"
#include "db/read-only-driver.hh"
#include "exec/task-runner.hh"
#include "job.hh"
#include "runtime.hh"

using std::cerr;
using std::endl;
using std::sprintf;

namespace flint {
namespace exec {

namespace {
const int kFilenameLength = 96;
}

JobRunner::JobRunner(TaskRunner *tr, int id)
	: tr_(tr)
	, dir_(new char[kFilenameLength])
	, generated_bc_(new char[kFilenameLength])
	, generated_db_(new char[kFilenameLength])
	, generated_init_(new char[kFilenameLength])
	, stored_(new char[kFilenameLength])
	, isd_(new char[kFilenameLength])
{
	sprintf(dir_.get(), "%s/%d", tr_->dir(), id);
	sprintf(generated_bc_.get(), "%s/generated-bc", dir_.get());
	sprintf(generated_db_.get(), "%s/generated.db", dir_.get());
	sprintf(generated_init_.get(), "%s/generated-init", dir_.get());
	sprintf(stored_.get(), "%s/stored", dir_.get());
	sprintf(isd_.get(), "%s/isd", dir_.get());
}

bool JobRunner::Run()
{
	{
		db::ReadOnlyDriver g(generated_db_.get());
		if (!compiler::Compile(g.db(), "parameter_eqs", "assign", generated_bc_.get()))
			return false;
	}
	if (!runtime::Init(tr_->GetDatabase(), tr_->generated_layout(), generated_bc_.get(), generated_init_.get()))
		return false;
	{
		boost::system::error_code ec;
		boost::filesystem::copy_file(tr_->init(), stored_.get(), ec);
		if (ec) {
			cerr << "failed to copy " << tr_->init()
				 << " to " << stored_.get()
				 << ": " << ec << endl;
			return false;
		}
	}
	if (!job::Store(tr_->GetDatabase(), tr_->generated_layout(), generated_init_.get(), tr_->layout(), stored_.get()))
		return false;
	return job::Job(tr_->dir(), dir_.get(), stored_.get(), isd_.get(), tr_->reader(), tr_->GetModelDatabase());
}

}
}
<commit_msg>drop unused #include<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:set ts=4 sw=4 sts=4 noet: */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "exec/job-runner.hh"

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>

#define BOOST_FILESYSTEM_NO_DEPRECATED
#include <boost/filesystem.hpp>

#include "compiler.hh"
#include "db/read-only-driver.hh"
#include "exec/task-runner.hh"
#include "job.hh"
#include "runtime.hh"

using std::cerr;
using std::endl;
using std::sprintf;

namespace flint {
namespace exec {

namespace {
const int kFilenameLength = 96;
}

JobRunner::JobRunner(TaskRunner *tr, int id)
	: tr_(tr)
	, dir_(new char[kFilenameLength])
	, generated_bc_(new char[kFilenameLength])
	, generated_db_(new char[kFilenameLength])
	, generated_init_(new char[kFilenameLength])
	, stored_(new char[kFilenameLength])
	, isd_(new char[kFilenameLength])
{
	sprintf(dir_.get(), "%s/%d", tr_->dir(), id);
	sprintf(generated_bc_.get(), "%s/generated-bc", dir_.get());
	sprintf(generated_db_.get(), "%s/generated.db", dir_.get());
	sprintf(generated_init_.get(), "%s/generated-init", dir_.get());
	sprintf(stored_.get(), "%s/stored", dir_.get());
	sprintf(isd_.get(), "%s/isd", dir_.get());
}

bool JobRunner::Run()
{
	{
		db::ReadOnlyDriver g(generated_db_.get());
		if (!compiler::Compile(g.db(), "parameter_eqs", "assign", generated_bc_.get()))
			return false;
	}
	if (!runtime::Init(tr_->GetDatabase(), tr_->generated_layout(), generated_bc_.get(), generated_init_.get()))
		return false;
	{
		boost::system::error_code ec;
		boost::filesystem::copy_file(tr_->init(), stored_.get(), ec);
		if (ec) {
			cerr << "failed to copy " << tr_->init()
				 << " to " << stored_.get()
				 << ": " << ec << endl;
			return false;
		}
	}
	if (!job::Store(tr_->GetDatabase(), tr_->generated_layout(), generated_init_.get(), tr_->layout(), stored_.get()))
		return false;
	return job::Job(tr_->dir(), dir_.get(), stored_.get(), isd_.get(), tr_->reader(), tr_->GetModelDatabase());
}

}
}
<|endoftext|>