<commit_before>#include "vtrc-client-base.h"

#include "boost/asio/io_service.hpp"
#include "google/protobuf/descriptor.h"

#include "vtrc-rpc-channel-c.h"
#include "vtrc-protocol-layer-c.h"
#include "vtrc-common/vtrc-mutex-typedefs.h"

#include "vtrc-bind.h"

namespace vtrc { namespace client {

    namespace basio = VTRC_ASIO;
    namespace gpb   = google::protobuf;

    namespace {

        typedef vtrc::weak_ptr<gpb::Service>        service_wptr;
        typedef vtrc::shared_ptr<gpb::Service>      service_sptr;
        typedef vtrc::shared_ptr<gpb::RpcChannel>   channel_sptr;

        typedef base::service_wrapper_type service_wrapper_type;
        typedef base::service_wrapper_wptr service_wrapper_wptr;
        typedef base::service_wrapper_sptr service_wrapper_sptr;

        typedef std::map<std::string, service_wptr> native_service_weak_map;
        typedef std::map<std::string, service_wrapper_wptr> service_weak_map;
        typedef std::map<std::string, service_wrapper_sptr> service_shared_map;

        typedef common::protocol_iface::call_type       proto_call_type;
        typedef common::protocol_iface::executor_type   executor_type;

        typedef common::connection_iface_sptr connection_iface_sptr;
    }

    struct base::impl {

        basio::io_service              *ios_;
        basio::io_service              *rpc_ios_;
        base                           *parent_;
        common::connection_iface_sptr   connection_;

        native_service_weak_map         weak_native_services_;
        service_weak_map                weak_services_;
        service_shared_map              hold_services_;
        vtrc::shared_mutex              services_lock_;

        base::service_factory_type      factory_;
        base::lowlevel_factory_type     ll_proto_factory_;

        vtrc::shared_mutex              factory_lock_;

        executor_type                   exec_;

        impl(basio::io_service &io, basio::io_service &rpcio)
            :ios_(&io)
            ,rpc_ios_(&rpcio)
        { }

        void reset_connection( common::connection_iface_sptr new_conn )
        {
            connection_ = new_conn;
        }

        rpc_channel_c *create_channel( )
        {
            rpc_channel_c *new_ch = new rpc_channel_c( connection_ );
            return new_ch;
        }

        rpc_channel_c *create_channel( unsigned opts )
        {
            rpc_channel_c *new_ch = new rpc_channel_c( connection_, opts );
            return new_ch;
        }

        bool ready( ) const
        {
            return connection_ ? connection_->get_protocol( ).ready( )
                               : false;
        }

        void disconnect( )
        {
            if( connection_ && connection_->active( ) ) {
                try {
                    connection_->close( );
                } catch( ... ) { }
            };
            connection_.reset( );
        }

        void set_default_exec(  )
        {
            namespace ph = vtrc::placeholders;
            exec_ = vtrc::bind( &impl::default_exec, this, ph::_1 );
        }

        void default_exec( proto_call_type call )
        {
            rpc_ios_->post( call );
        }

        void assign_call_executor( base::executor_type exec )
        {
            if( exec ) {
                exec_ = exec;
            } else {
                set_default_exec( );
            }
        }

        void assign_protocol_factory( base::lowlevel_factory_type factory )
        {
            ll_proto_factory_ = factory;
        }

        void assign_weak_handler( vtrc::weak_ptr<gpb::Service> serv )
        {
            service_sptr lock(serv.lock( ));
            if( lock ) {
                const std::string s_name(lock->GetDescriptor( )->full_name( ));
                vtrc::unique_shared_lock lk(services_lock_);
                weak_native_services_[s_name] = serv;
            }
        }

        void assign_handler( vtrc::shared_ptr<gpb::Service> serv )
        {
            assign_handler_wrap( parent_->wrap_service( serv ) );
        }

        void assign_handler_wrap( service_wrapper_sptr serv )
        {
            const std::string serv_name( serv->service( )
                                             ->GetDescriptor( )
                                             ->full_name( ));
            vtrc::upgradable_lock lk(services_lock_);
            service_shared_map::iterator f( hold_services_.find( serv_name ) );
            if( f != hold_services_.end( ) ) {
                f->second = serv;
                upgrade_to_unique ulk(lk);
                weak_services_[serv_name] = service_wrapper_wptr(serv);
            } else {
                upgrade_to_unique ulk(lk);
                hold_services_.insert( std::make_pair(serv_name, serv) );
                weak_services_[serv_name] = service_wrapper_wptr(serv);
            }
        }

        void assign_weak_handler_wrap( service_wrapper_wptr serv )
        {
            service_wrapper_sptr lock(serv.lock( ));
            if( lock ) {
                const std::string s_name(lock->service( )
                                             ->GetDescriptor( )
                                             ->full_name( ));
                vtrc::unique_shared_lock lk(services_lock_);
                weak_services_[s_name] = serv;
            }
        }

        void assign_service_factory( base::service_factory_type factory )
        {
            vtrc::unique_shared_lock lck(factory_lock_);
            factory_ = factory;
        }

        service_wrapper_sptr get_handler( const std::string &name )
        {
            service_wrapper_sptr result;

            {
                vtrc::upgradable_lock lk(services_lock_);
                service_weak_map::iterator f( weak_services_.find( name ) );
                if( f != weak_services_.end( ) ) {
                    result = f->second.lock( );
                    if( !result ) {
                        vtrc::upgrade_to_unique ulk(lk);
                        weak_services_.erase( f );
                    }
                }
            }

            // we don't have service here
            // have to find it in the "native map"
            if( !result ) {
                vtrc::upgradable_lock lk(services_lock_);

                native_service_weak_map::iterator f =
                                weak_native_services_.find( name );

                if( f != weak_native_services_.end( ) ) {
                    service_sptr res = f->second.lock( );
                    if( !res ) {
                        vtrc::upgrade_to_unique ulk(lk);
                        weak_native_services_.erase( f );
                    } else {
                        result = parent_->wrap_service( res );
                    }
                }
            }

            // Ok. last chance to get the service is to create it
            if( !result ) {
                vtrc::shared_lock shl( factory_lock_ );
                if( factory_ ) {
                    result = factory_( name );
                }
            }

            return result;
        }

        void erase_rpc_handler( const std::string &name )
        {
            vtrc::unique_shared_lock lk(services_lock_);

            service_shared_map::iterator sf( hold_services_.find( name ) );
            service_weak_map::iterator   wf( weak_services_.find( name ) );

            if( sf != hold_services_.end( ) ) hold_services_.erase( sf );
            if( wf != weak_services_.end( ) ) weak_services_.erase( wf );
            weak_native_services_.erase( name );
        }

        void erase_all_rpc_handlers( )
        {
            vtrc::unique_shared_lock lk(services_lock_);
            hold_services_.clear( );
            weak_services_.clear( );
        }
    };

    base::base( VTRC_ASIO::io_service &ios )
        :impl_(new impl(ios, ios))
    {
        impl_->parent_ = this;
    }

    base::base( VTRC_ASIO::io_service &ios,
                VTRC_ASIO::io_service &rpc_ios )
        :impl_(new impl(ios, rpc_ios))
    {
        impl_->parent_ = this;
    }

    base::base( common::pool_pair &pools )
        :impl_(new impl(pools.get_io_service(), pools.get_rpc_service( )))
    {
        impl_->parent_ = this;
    }

    void base::reset_connection( common::connection_iface_sptr new_conn )
    {
        impl_->reset_connection( new_conn );
    }

    common::protocol_iface *base::init_protocol( connection_iface_sptr c )
    {
        /// base!
//        vtrc::unique_ptr<protocol_layer_c> proto
//                        ( new protocol_layer_c( c.get( ), this, impl_ ) );
//        on_connect_( );
//        proto->init( );
//        impl_->connection_ = c;
//        return proto.release( );
        throw std::runtime_error( "not ready!" );
        return nullptr;
    }

    common::connection_iface_sptr base::connection( )
    {
        return impl_->connection_;
    }

    vtrc::weak_ptr<base> base::weak_from_this( )
    {
        return vtrc::weak_ptr<base>(shared_from_this());
    }

    vtrc::weak_ptr<base const> base::weak_from_this( ) const
    {
        return vtrc::weak_ptr<base const>(shared_from_this());
    }

    VTRC_ASIO::io_service &base::get_io_service( )
    {
        return *impl_->ios_;
    }

    const VTRC_ASIO::io_service &base::get_io_service( ) const
    {
        return *impl_->ios_;
    }

    VTRC_ASIO::io_service &base::get_rpc_service( )
    {
        return *impl_->rpc_ios_;
    }

    const VTRC_ASIO::io_service &base::get_rpc_service( ) const
    {
        return *impl_->rpc_ios_;
    }

    common::rpc_channel *base::create_channel( )
    {
        return impl_->create_channel( );
    }

    common::rpc_channel *base::create_channel( unsigned flags )
    {
        return impl_->create_channel(flags);
    }

    bool base::ready( ) const
    {
        return impl_->ready( );
    }

    void base::disconnect( )
    {
        impl_->disconnect( );
    }

    void base::assign_rpc_handler( vtrc::shared_ptr<gpb::Service> serv )
    {
        impl_->assign_handler( serv );
    }

    void base::assign_weak_rpc_handler(vtrc::weak_ptr<gpb::Service> serv)
    {
        impl_->assign_weak_handler( serv );
    }

    void base::assign_rpc_handler( service_wrapper_sptr handler )
    {
        impl_->assign_handler_wrap( handler );
    }

    void base::assign_weak_rpc_handler( service_wrapper_wptr handler)
    {
        impl_->assign_weak_handler_wrap( handler );
    }

    void base::assign_service_factory( service_factory_type factory )
    {
        impl_->assign_service_factory( factory );
    }

    service_wrapper_sptr base::get_rpc_handler( const std::string &name )
    {
        return impl_->get_handler( name );
    }

    void base::erase_rpc_handler( service_sptr handler)
    {
        impl_->erase_rpc_handler( handler->GetDescriptor( )->full_name( ) );
    }

    void base::erase_rpc_handler( const std::string &name )
    {
        impl_->erase_rpc_handler( name );
    }

    void base::erase_all_rpc_handlers( )
    {
        impl_->erase_all_rpc_handlers( );
    }

    void base::assign_lowlevel_protocol_factory( lowlevel_factory_type factory )
    {
        impl_->assign_protocol_factory( factory );
    }

    base::lowlevel_factory_type base::lowlevel_protocol_factory( )
    {
        return impl_->ll_proto_factory_;
    }

    void base::assign_call_executor( executor_type exec )
    {
        impl_->assign_call_executor( exec );
    }

    base::executor_type base::call_executor( )
    {
        return impl_->exec_;
    }

    void base::execute( common::protocol_iface::call_type call )
    {
        impl_->exec_( call );
    }

}}
<commit_msg>fix disconnect<commit_after>#include "vtrc-client-base.h"

#include "boost/asio/io_service.hpp"
#include "google/protobuf/descriptor.h"

#include "vtrc-rpc-channel-c.h"
#include "vtrc-protocol-layer-c.h"
#include "vtrc-common/vtrc-mutex-typedefs.h"

#include "vtrc-bind.h"

namespace vtrc { namespace client {

    namespace basio = VTRC_ASIO;
    namespace gpb   = google::protobuf;

    namespace {

        typedef vtrc::weak_ptr<gpb::Service>        service_wptr;
        typedef vtrc::shared_ptr<gpb::Service>      service_sptr;
        typedef vtrc::shared_ptr<gpb::RpcChannel>   channel_sptr;

        typedef base::service_wrapper_type service_wrapper_type;
        typedef base::service_wrapper_wptr service_wrapper_wptr;
        typedef base::service_wrapper_sptr service_wrapper_sptr;

        typedef std::map<std::string, service_wptr> native_service_weak_map;
        typedef std::map<std::string, service_wrapper_wptr> service_weak_map;
        typedef std::map<std::string, service_wrapper_sptr> service_shared_map;

        typedef common::protocol_iface::call_type       proto_call_type;
        typedef common::protocol_iface::executor_type   executor_type;

        typedef common::connection_iface_sptr connection_iface_sptr;
    }

    struct base::impl {

        basio::io_service              *ios_;
        basio::io_service              *rpc_ios_;
        base                           *parent_;
        common::connection_iface_sptr   connection_;

        native_service_weak_map         weak_native_services_;
        service_weak_map                weak_services_;
        service_shared_map              hold_services_;
        vtrc::shared_mutex              services_lock_;

        base::service_factory_type      factory_;
        base::lowlevel_factory_type     ll_proto_factory_;

        vtrc::shared_mutex              factory_lock_;

        executor_type                   exec_;

        impl(basio::io_service &io, basio::io_service &rpcio)
            :ios_(&io)
            ,rpc_ios_(&rpcio)
        { }

        void reset_connection( common::connection_iface_sptr new_conn )
        {
            connection_ = new_conn;
        }

        rpc_channel_c *create_channel( )
        {
            rpc_channel_c *new_ch = new rpc_channel_c( connection_ );
            return new_ch;
        }

        rpc_channel_c *create_channel( unsigned opts )
        {
            rpc_channel_c *new_ch = new rpc_channel_c( connection_, opts );
            return new_ch;
        }

        bool ready( ) const
        {
            return connection_ ? connection_->get_protocol( ).ready( )
                               : false;
        }

        void disconnect( )
        {
            if( connection_ && connection_->active( ) ) {
                try {
                    connection_->close( );
                } catch( ... ) { }
            };
            //connection_.reset( );
        }

        void set_default_exec(  )
        {
            namespace ph = vtrc::placeholders;
            exec_ = vtrc::bind( &impl::default_exec, this, ph::_1 );
        }

        void default_exec( proto_call_type call )
        {
            rpc_ios_->post( call );
        }

        void assign_call_executor( base::executor_type exec )
        {
            if( exec ) {
                exec_ = exec;
            } else {
                set_default_exec( );
            }
        }

        void assign_protocol_factory( base::lowlevel_factory_type factory )
        {
            ll_proto_factory_ = factory;
        }

        void assign_weak_handler( vtrc::weak_ptr<gpb::Service> serv )
        {
            service_sptr lock(serv.lock( ));
            if( lock ) {
                const std::string s_name(lock->GetDescriptor( )->full_name( ));
                vtrc::unique_shared_lock lk(services_lock_);
                weak_native_services_[s_name] = serv;
            }
        }

        void assign_handler( vtrc::shared_ptr<gpb::Service> serv )
        {
            assign_handler_wrap( parent_->wrap_service( serv ) );
        }

        void assign_handler_wrap( service_wrapper_sptr serv )
        {
            const std::string serv_name( serv->service( )
                                             ->GetDescriptor( )
                                             ->full_name( ));
            vtrc::upgradable_lock lk(services_lock_);
            service_shared_map::iterator f( hold_services_.find( serv_name ) );
            if( f != hold_services_.end( ) ) {
                f->second = serv;
                upgrade_to_unique ulk(lk);
                weak_services_[serv_name] = service_wrapper_wptr(serv);
            } else {
                upgrade_to_unique ulk(lk);
                hold_services_.insert( std::make_pair(serv_name, serv) );
                weak_services_[serv_name] = service_wrapper_wptr(serv);
            }
        }

        void assign_weak_handler_wrap( service_wrapper_wptr serv )
        {
            service_wrapper_sptr lock(serv.lock( ));
            if( lock ) {
                const std::string s_name(lock->service( )
                                             ->GetDescriptor( )
                                             ->full_name( ));
                vtrc::unique_shared_lock lk(services_lock_);
                weak_services_[s_name] = serv;
            }
        }

        void assign_service_factory( base::service_factory_type factory )
        {
            vtrc::unique_shared_lock lck(factory_lock_);
            factory_ = factory;
        }

        service_wrapper_sptr get_handler( const std::string &name )
        {
            service_wrapper_sptr result;

            {
                vtrc::upgradable_lock lk(services_lock_);
                service_weak_map::iterator f( weak_services_.find( name ) );
                if( f != weak_services_.end( ) ) {
                    result = f->second.lock( );
                    if( !result ) {
                        vtrc::upgrade_to_unique ulk(lk);
                        weak_services_.erase( f );
                    }
                }
            }

            // we don't have service here
            // have to find it in the "native map"
            if( !result ) {
                vtrc::upgradable_lock lk(services_lock_);

                native_service_weak_map::iterator f =
                                weak_native_services_.find( name );

                if( f != weak_native_services_.end( ) ) {
                    service_sptr res = f->second.lock( );
                    if( !res ) {
                        vtrc::upgrade_to_unique ulk(lk);
                        weak_native_services_.erase( f );
                    } else {
                        result = parent_->wrap_service( res );
                    }
                }
            }

            // Ok. last chance to get the service is to create it
            if( !result ) {
                vtrc::shared_lock shl( factory_lock_ );
                if( factory_ ) {
                    result = factory_( name );
                }
            }

            return result;
        }

        void erase_rpc_handler( const std::string &name )
        {
            vtrc::unique_shared_lock lk(services_lock_);

            service_shared_map::iterator sf( hold_services_.find( name ) );
            service_weak_map::iterator   wf( weak_services_.find( name ) );

            if( sf != hold_services_.end( ) ) hold_services_.erase( sf );
            if( wf != weak_services_.end( ) ) weak_services_.erase( wf );
            weak_native_services_.erase( name );
        }

        void erase_all_rpc_handlers( )
        {
            vtrc::unique_shared_lock lk(services_lock_);
            hold_services_.clear( );
            weak_services_.clear( );
        }
    };

    base::base( VTRC_ASIO::io_service &ios )
        :impl_(new impl(ios, ios))
    {
        impl_->parent_ = this;
    }

    base::base( VTRC_ASIO::io_service &ios,
                VTRC_ASIO::io_service &rpc_ios )
        :impl_(new impl(ios, rpc_ios))
    {
        impl_->parent_ = this;
    }

    base::base( common::pool_pair &pools )
        :impl_(new impl(pools.get_io_service(), pools.get_rpc_service( )))
    {
        impl_->parent_ = this;
    }

    void base::reset_connection( common::connection_iface_sptr new_conn )
    {
        impl_->reset_connection( new_conn );
    }

    common::protocol_iface *base::init_protocol( connection_iface_sptr c )
    {
        /// base!
//        vtrc::unique_ptr<protocol_layer_c> proto
//                        ( new protocol_layer_c( c.get( ), this, impl_ ) );
//        on_connect_( );
//        proto->init( );
//        impl_->connection_ = c;
//        return proto.release( );
        throw std::runtime_error( "not ready!" );
        return nullptr;
    }

    common::connection_iface_sptr base::connection( )
    {
        return impl_->connection_;
    }

    vtrc::weak_ptr<base> base::weak_from_this( )
    {
        return vtrc::weak_ptr<base>(shared_from_this());
    }

    vtrc::weak_ptr<base const> base::weak_from_this( ) const
    {
        return vtrc::weak_ptr<base const>(shared_from_this());
    }

    VTRC_ASIO::io_service &base::get_io_service( )
    {
        return *impl_->ios_;
    }

    const VTRC_ASIO::io_service &base::get_io_service( ) const
    {
        return *impl_->ios_;
    }

    VTRC_ASIO::io_service &base::get_rpc_service( )
    {
        return *impl_->rpc_ios_;
    }

    const VTRC_ASIO::io_service &base::get_rpc_service( ) const
    {
        return *impl_->rpc_ios_;
    }

    common::rpc_channel *base::create_channel( )
    {
        return impl_->create_channel( );
    }

    common::rpc_channel *base::create_channel( unsigned flags )
    {
        return impl_->create_channel(flags);
    }

    bool base::ready( ) const
    {
        return impl_->ready( );
    }

    void base::disconnect( )
    {
        impl_->disconnect( );
    }

    void base::assign_rpc_handler( vtrc::shared_ptr<gpb::Service> serv )
    {
        impl_->assign_handler( serv );
    }

    void base::assign_weak_rpc_handler(vtrc::weak_ptr<gpb::Service> serv)
    {
        impl_->assign_weak_handler( serv );
    }

    void base::assign_rpc_handler( service_wrapper_sptr handler )
    {
        impl_->assign_handler_wrap( handler );
    }

    void base::assign_weak_rpc_handler( service_wrapper_wptr handler)
    {
        impl_->assign_weak_handler_wrap( handler );
    }

    void base::assign_service_factory( service_factory_type factory )
    {
        impl_->assign_service_factory( factory );
    }

    service_wrapper_sptr base::get_rpc_handler( const std::string &name )
    {
        return impl_->get_handler( name );
    }

    void base::erase_rpc_handler( service_sptr handler)
    {
        impl_->erase_rpc_handler( handler->GetDescriptor( )->full_name( ) );
    }

    void base::erase_rpc_handler( const std::string &name )
    {
        impl_->erase_rpc_handler( name );
    }

    void base::erase_all_rpc_handlers( )
    {
        impl_->erase_all_rpc_handlers( );
    }

    void base::assign_lowlevel_protocol_factory( lowlevel_factory_type factory )
    {
        impl_->assign_protocol_factory( factory );
    }

    base::lowlevel_factory_type base::lowlevel_protocol_factory( )
    {
        return impl_->ll_proto_factory_;
    }

    void base::assign_call_executor( executor_type exec )
    {
        impl_->assign_call_executor( exec );
    }

    base::executor_type base::call_executor( )
    {
        return impl_->exec_;
    }

    void base::execute( common::protocol_iface::call_type call )
    {
        impl_->exec_( call );
    }

}}
<|endoftext|>


<commit_before>#include "acmacs-base/range-v3.hh"
#include "acmacs-whocc/sheet.hh"
#include "acmacs-whocc/log.hh"

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

bool acmacs::sheet::v1::Sheet::matches(const std::regex& re, const cell_t& cell)
{
    return std::visit(
        [&re, &cell]<typename Content>(const Content& arg) {
            if constexpr (std::is_same_v<Content, std::string>)
                return std::regex_search(arg, re);
            else
                return std::regex_search(fmt::format("{}", cell), re); // CDC id is a number in CDC tables, still we want to match
        },
        cell);

} // acmacs::sheet::v1::Sheet::matches

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

bool acmacs::sheet::v1::Sheet::matches(const std::regex& re, std::smatch& match, const cell_t& cell)
{
    return std::visit(
        [&re, &match]<typename Content>(const Content& arg) {
            if constexpr (std::is_same_v<Content, std::string>)
                return std::regex_search(arg, match, re);
            else
                return false;
        },
        cell);

} // acmacs::sheet::v1::Sheet::matches

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

size_t acmacs::sheet::v1::Sheet::size(const cell_t& cell) const
{
    return std::visit(
        []<typename Content>(const Content& arg) {
            if constexpr (std::is_same_v<Content, std::string>)
                return arg.size();
            else
                return 0ul;
        },
        cell);

} // acmacs::sheet::v1::Sheet::size

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

#include "acmacs-base/global-constructors-push.hh"

static const std::regex re_titer{"^(<|[<>]?[1-9][0-9]{0,5}|N[DA]|QNS|\\*)$", acmacs::regex::icase};

#include "acmacs-base/diagnostics-pop.hh"

bool acmacs::sheet::v1::Sheet::maybe_titer(const cell_t& cell) const
{
    return std::visit(
        []<typename Content>(const Content& arg) {
            if constexpr (std::is_same_v<Content, std::string>)
                return std::regex_search(arg, re_titer);
            else if constexpr (std::is_same_v<Content, double> || std::is_same_v<Content, long>)
                return arg > 0;
            else
                return false;
        },
        cell);

} // acmacs::sheet::v1::Sheet::maybe_titer

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

acmacs::sheet::v1::column_range acmacs::sheet::v1::Sheet::titer_range(nrow_t row) const
{
    range<ncol_t> longest;
    range<ncol_t> current;
    const auto update = [&longest, &current] {
        if (current.valid()) {
            if (!longest.valid() || longest.length() < current.length()) {
                longest = current;
                // AD_DEBUG("longest {}: {}", row, longest);
            }
            current = range<ncol_t>{};
        }
    };

    for (auto col = ncol_t{0}; col < number_of_columns(); ++col) {
        if (maybe_titer(row, col)) {
            if (!current.valid())
                current.first = col;
            current.second = col;
            // AD_DEBUG("titer {}{}: {} --> {}", row, col, cell(row, col), current);
        }
        else
            update();
    }
    update();
    return longest;

} // acmacs::sheet::v1::Sheet::titer_range

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

std::vector<acmacs::sheet::cell_match_t> acmacs::sheet::v1::Sheet::grep(const std::regex& rex, const cell_addr_t& min, const cell_addr_t& max) const
{
    std::vector<cell_match_t> result;
    for (auto row = min.row; row < max.row; ++row) {
        for (auto col = min.col; col < max.col; ++col) {
            const auto cl = cell(row, col);
            // AD_DEBUG("Sheet::grep {} {} \"{}\"", row, col, cl);
            std::smatch match;
            if (matches(rex, match, cl)) {
                cell_match_t cm{.row = row, .col = col, .matches = std::vector<std::string>(match.size())};
                std::transform(std::cbegin(match), std::cend(match), std::begin(cm.matches), [](const auto& submatch) { return submatch.str(); });
                result.push_back(std::move(cm));
            }
        }
    }
    return result;

} // acmacs::sheet::v1::Sheet::grep

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>NIID parser<commit_after>#include "acmacs-base/range-v3.hh"
#include "acmacs-whocc/sheet.hh"
#include "acmacs-whocc/log.hh"

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

bool acmacs::sheet::v1::Sheet::matches(const std::regex& re, const cell_t& cell)
{
    return std::visit(
        [&re, &cell]<typename Content>(const Content& arg) {
            if constexpr (std::is_same_v<Content, std::string>)
                return std::regex_search(arg, re);
            else
                return std::regex_search(fmt::format("{}", cell), re); // CDC id is a number in CDC tables, still we want to match
        },
        cell);

} // acmacs::sheet::v1::Sheet::matches

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

bool acmacs::sheet::v1::Sheet::matches(const std::regex& re, std::smatch& match, const cell_t& cell)
{
    return std::visit(
        [&re, &match]<typename Content>(const Content& arg) {
            if constexpr (std::is_same_v<Content, std::string>)
                return std::regex_search(arg, match, re);
            else
                return false;
        },
        cell);

} // acmacs::sheet::v1::Sheet::matches

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

size_t acmacs::sheet::v1::Sheet::size(const cell_t& cell) const
{
    return std::visit(
        []<typename Content>(const Content& arg) {
            if constexpr (std::is_same_v<Content, std::string>)
                return arg.size();
            else
                return 0ul;
        },
        cell);

} // acmacs::sheet::v1::Sheet::size

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

#include "acmacs-base/global-constructors-push.hh"

static const std::regex re_titer{R"(^(<|[<>]?\s*[1-9][0-9]{0,5}|N[DA]|QNS|\*)$)", acmacs::regex::icase};

#include "acmacs-base/diagnostics-pop.hh"

bool acmacs::sheet::v1::Sheet::maybe_titer(const cell_t& cell) const
{
    return std::visit(
        []<typename Content>(const Content& arg) {
            if constexpr (std::is_same_v<Content, std::string>)
                return std::regex_search(arg, re_titer);
            else if constexpr (std::is_same_v<Content, double> || std::is_same_v<Content, long>)
                return arg > 0;
            else
                return false;
        },
        cell);

} // acmacs::sheet::v1::Sheet::maybe_titer

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

acmacs::sheet::v1::column_range acmacs::sheet::v1::Sheet::titer_range(nrow_t row) const
{
    range<ncol_t> longest;
    range<ncol_t> current;
    const auto update = [&longest, &current] {
        if (current.valid()) {
            if (!longest.valid() || longest.length() < current.length()) {
                longest = current;
                // AD_DEBUG("longest {}: {}", row, longest);
            }
            current = range<ncol_t>{};
        }
    };

    for (auto col = ncol_t{0}; col < number_of_columns(); ++col) {
        if (maybe_titer(row, col)) {
            if (!current.valid())
                current.first = col;
            current.second = col;
            // AD_DEBUG("titer {}{}: {} --> {}", row, col, cell(row, col), current);
        }
        else
            update();
    }
    update();
    return longest;

} // acmacs::sheet::v1::Sheet::titer_range

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

std::vector<acmacs::sheet::cell_match_t> acmacs::sheet::v1::Sheet::grep(const std::regex& rex, const cell_addr_t& min, const cell_addr_t& max) const
{
    std::vector<cell_match_t> result;
    for (auto row = min.row; row < max.row; ++row) {
        for (auto col = min.col; col < max.col; ++col) {
            const auto cl = cell(row, col);
            // AD_DEBUG("Sheet::grep {} {} \"{}\"", row, col, cl);
            std::smatch match;
            if (matches(rex, match, cl)) {
                cell_match_t cm{.row = row, .col = col, .matches = std::vector<std::string>(match.size())};
                std::transform(std::cbegin(match), std::cend(match), std::begin(cm.matches), [](const auto& submatch) { return submatch.str(); });
                result.push_back(std::move(cm));
            }
        }
    }
    return result;

} // acmacs::sheet::v1::Sheet::grep

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include <algorithm>
#include <iostream>
#include <string>

#include <boost/program_options.hpp>

#include <plasp/LanguageDetection.h>
#include <plasp/pddl/Description.h>
#include <plasp/pddl/TranslatorASP.h>
#include <plasp/sas/Description.h>
#include <plasp/sas/TranslatorASP.h>
#include <plasp/utils/LogStream.h>
#include <plasp/utils/TranslatorException.h>

int main(int argc, char **argv)
{
	namespace po = boost::program_options;

	po::options_description description("Allowed options");
	description.add_options()
		("help,h", "Display this help message.")
		("version,v", "Display version information.")
		("input,i", po::value<std::vector<std::string>>(), "Specify the PDDL or SAS input file.")
		("language,l", po::value<std::string>(), "Specify the input language (sas or pddl). Omit for automatic detection.")
		("warning-level", po::value<std::string>()->default_value("normal"), "Specify whether to output warnings normally (normal), to treat them as critical errors (error), or to ignore them (ignore).")
		("color", po::value<std::string>()->default_value("auto"), "Specify whether to colorize the output (always, never, or auto).");

	po::positional_options_description positionalOptionsDescription;
	positionalOptionsDescription.add("input", -1);

	po::variables_map variablesMap;

	const auto printHelp =
		[&]()
		{
			std::cout << "Usage: plasp [files] [options]" << std::endl;
			std::cout << "Translate PDDL instances to ASP facts." << std::endl << std::endl;

			std::cout << description;
		};

	plasp::utils::Logger logger;

	try
	{
		po::store(po::command_line_parser(argc, argv)
			.options(description)
			.positional(positionalOptionsDescription)
			.run(),
			variablesMap);
		po::notify(variablesMap);
	}
	catch (const po::error &e)
	{
		logger.logError(e.what());
		std::cout << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	if (variablesMap.count("help"))
	{
		printHelp();
		return EXIT_SUCCESS;
	}

	if (variablesMap.count("version"))
	{
		std::cout << "plasp version 3.0.2" << std::endl;
		return EXIT_SUCCESS;
	}

	const auto warningLevel = variablesMap["warning-level"].as<std::string>();

	if (warningLevel == "error")
		logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Error);
	else if (warningLevel == "ignore")
		logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Ignore);
	else if (warningLevel == "normal")
		logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Normal);
	else
	{
		logger.logError("unknown warning level “" + warningLevel + "”");
		std::cout << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	const auto colorPolicy = variablesMap["color"].as<std::string>();

	if (colorPolicy == "auto")
		logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Auto);
	else if (colorPolicy == "never")
		logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Never);
	else if (colorPolicy == "always")
		logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Always);
	else
	{
		logger.logError("unknown color policy “" + colorPolicy + "”");
		std::cout << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	try
	{
		plasp::utils::Parser<plasp::utils::CaseInsensitiveParserPolicy> parser;

		if (variablesMap.count("input"))
		{
			const auto &inputFiles = variablesMap["input"].as<std::vector<std::string>>();

			std::for_each(inputFiles.cbegin(), inputFiles.cend(),
				[&](const auto &inputFile)
				{
					parser.read(inputFile);
				});
		}
		else
			parser.read("std::cin", std::cin);

		const auto detectLanguage =
			[&]()
			{
				if (variablesMap.count("language") == 0)
					return plasp::detectLanguage(parser);

				const auto languageName = variablesMap["language"].as<std::string>();

				return plasp::Language::fromString(languageName);
			};

		const auto language = detectLanguage();

		if (language == plasp::Language::Type::Unknown)
		{
			logger.logError("unknown input language");
			std::cout << std::endl;
			printHelp();
			return EXIT_FAILURE;
		}

		if (language == plasp::Language::Type::PDDL)
		{
			auto pddlLogger = logger;
			auto context = plasp::pddl::Context(std::move(parser), std::move(pddlLogger));
			auto description = plasp::pddl::Description::fromContext(std::move(context));
			const auto translator = plasp::pddl::TranslatorASP(description, description.context().logger.outputStream());
			translator.translate();
		}
		else if (language == plasp::Language::Type::SAS)
		{
			const auto description = plasp::sas::Description::fromParser(std::move(parser));
			const auto translator = plasp::sas::TranslatorASP(description, logger.outputStream());
			translator.translate();
		}
	}
	catch (const plasp::utils::ParserException &e)
	{
		logger.logError(e.coordinate(), e.message());
		return EXIT_FAILURE;
	}
	catch (const plasp::utils::TranslatorException &e)
	{
		logger.logError(e.what());
		return EXIT_FAILURE;
	}
	catch (const std::exception &e)
	{
		logger.logError(e.what());
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}
<commit_msg>Version bump after release 3.0.2.<commit_after>#include <algorithm>
#include <iostream>
#include <string>

#include <boost/program_options.hpp>

#include <plasp/LanguageDetection.h>
#include <plasp/pddl/Description.h>
#include <plasp/pddl/TranslatorASP.h>
#include <plasp/sas/Description.h>
#include <plasp/sas/TranslatorASP.h>
#include <plasp/utils/LogStream.h>
#include <plasp/utils/TranslatorException.h>

int main(int argc, char **argv)
{
	namespace po = boost::program_options;

	po::options_description description("Allowed options");
	description.add_options()
		("help,h", "Display this help message.")
		("version,v", "Display version information.")
		("input,i", po::value<std::vector<std::string>>(), "Specify the PDDL or SAS input file.")
		("language,l", po::value<std::string>(), "Specify the input language (sas or pddl). Omit for automatic detection.")
		("warning-level", po::value<std::string>()->default_value("normal"), "Specify whether to output warnings normally (normal), to treat them as critical errors (error), or to ignore them (ignore).")
		("color", po::value<std::string>()->default_value("auto"), "Specify whether to colorize the output (always, never, or auto).");

	po::positional_options_description positionalOptionsDescription;
	positionalOptionsDescription.add("input", -1);

	po::variables_map variablesMap;

	const auto printHelp =
		[&]()
		{
			std::cout << "Usage: plasp [files] [options]" << std::endl;
			std::cout << "Translate PDDL instances to ASP facts." << std::endl << std::endl;

			std::cout << description;
		};

	plasp::utils::Logger logger;

	try
	{
		po::store(po::command_line_parser(argc, argv)
			.options(description)
			.positional(positionalOptionsDescription)
			.run(),
			variablesMap);
		po::notify(variablesMap);
	}
	catch (const po::error &e)
	{
		logger.logError(e.what());
		std::cout << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	if (variablesMap.count("help"))
	{
		printHelp();
		return EXIT_SUCCESS;
	}

	if (variablesMap.count("version"))
	{
		std::cout << "plasp version 3.0.2-git" << std::endl;
		return EXIT_SUCCESS;
	}

	const auto warningLevel = variablesMap["warning-level"].as<std::string>();

	if (warningLevel == "error")
		logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Error);
	else if (warningLevel == "ignore")
		logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Ignore);
	else if (warningLevel == "normal")
		logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Normal);
	else
	{
		logger.logError("unknown warning level “" + warningLevel + "”");
		std::cout << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	const auto colorPolicy = variablesMap["color"].as<std::string>();

	if (colorPolicy == "auto")
		logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Auto);
	else if (colorPolicy == "never")
		logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Never);
	else if (colorPolicy == "always")
		logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Always);
	else
	{
		logger.logError("unknown color policy “" + colorPolicy + "”");
		std::cout << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	try
	{
		plasp::utils::Parser<plasp::utils::CaseInsensitiveParserPolicy> parser;

		if (variablesMap.count("input"))
		{
			const auto &inputFiles = variablesMap["input"].as<std::vector<std::string>>();

			std::for_each(inputFiles.cbegin(), inputFiles.cend(),
				[&](const auto &inputFile)
				{
					parser.read(inputFile);
				});
		}
		else
			parser.read("std::cin", std::cin);

		const auto detectLanguage =
			[&]()
			{
				if (variablesMap.count("language") == 0)
					return plasp::detectLanguage(parser);

				const auto languageName = variablesMap["language"].as<std::string>();

				return plasp::Language::fromString(languageName);
			};

		const auto language = detectLanguage();

		if (language == plasp::Language::Type::Unknown)
		{
			logger.logError("unknown input language");
			std::cout << std::endl;
			printHelp();
			return EXIT_FAILURE;
		}

		if (language == plasp::Language::Type::PDDL)
		{
			auto pddlLogger = logger;
			auto context = plasp::pddl::Context(std::move(parser), std::move(pddlLogger));
			auto description = plasp::pddl::Description::fromContext(std::move(context));
			const auto translator = plasp::pddl::TranslatorASP(description, description.context().logger.outputStream());
			translator.translate();
		}
		else if (language == plasp::Language::Type::SAS)
		{
			const auto description = plasp::sas::Description::fromParser(std::move(parser));
			const auto translator = plasp::sas::TranslatorASP(description, logger.outputStream());
			translator.translate();
		}
	}
	catch (const plasp::utils::ParserException &e)
	{
		logger.logError(e.coordinate(), e.message());
		return EXIT_FAILURE;
	}
	catch (const plasp::utils::TranslatorException &e)
	{
		logger.logError(e.what());
		return EXIT_FAILURE;
	}
	catch (const std::exception &e)
	{
		logger.logError(e.what());
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "bitcoinamountfield.h"
#include "bitcoinunits.h"
#include "ntp1/ntp1listelementtokendata.h"
#include "qvaluecombobox.h"

#include "guiconstants.h"

#include <QApplication>
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QRegExpValidator>
#include <qmath.h>

BitcoinAmountField::BitcoinAmountField(bool EnableNTP1Tokens, QWidget* parent)
    : QWidget(parent), amount(0), currentUnit(-1)
{
    enableNTP1Tokens = EnableNTP1Tokens;

    amount = new QDoubleSpinBox(this);
    amount->setLocale(QLocale::c());
    amount->setDecimals(8);
    amount->installEventFilter(this);
    amount->setMaximumWidth(170);
    amount->setSingleStep(0.001);

    QHBoxLayout* layout = new QHBoxLayout(this);
    layout->addWidget(amount);
    unit = new QValueComboBox(this);
    unit->setModel(new BitcoinUnits(this));
    layout->addWidget(unit);
    //    layout->addStretch(1);
    layout->setContentsMargins(0, 0, 0, 0);

    if (enableNTP1Tokens) {
        tokenKindsComboBox = new QComboBox;
        tokenKindsComboBox->addItem(QIcon(QStringLiteral(":/icons/bitcoin")), "NEBL");
        layout->addWidget(tokenKindsComboBox);

        refreshTokensButton = new QToolButton;
        QIcon icon;
        icon.addFile(QStringLiteral(":/icons/refresh"), QSize(), QIcon::Normal, QIcon::Off);
        refreshTokensButton->setIcon(icon);
        refreshTokensButton->setToolTip("Refresh tokens list");
        layout->addWidget(refreshTokensButton);

        connect(refreshTokensButton, &QToolButton::clicked, this,
                &BitcoinAmountField::slot_updateTokensList);
        connect(tokenKindsComboBox,
                static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
                &BitcoinAmountField::slot_tokenChanged);
    }

    setLayout(layout);

    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(amount);

    // If one if the widgets changes, the combined content changes as well
    connect(amount, SIGNAL(valueChanged(QString)), this, SIGNAL(textChanged()));
    connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));
    if (enableNTP1Tokens) {
        connect(tokenKindsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));
    }

    // Set default based on configuration
    unitChanged(unit->currentIndex());
}

void BitcoinAmountField::setText(const QString& text)
{
    if (text.isEmpty())
        amount->clear();
    else
        amount->setValue(text.toDouble());
}

void BitcoinAmountField::clear()
{
    amount->clear();
    unit->setCurrentIndex(0);
    if (enableNTP1Tokens) {
        tokenKindsComboBox->setCurrentIndex(0);
        slot_updateTokensList();
    }
}

bool BitcoinAmountField::validate()
{
    bool valid = true;
    if (amount->value() == 0.0)
        valid = false;
    if (valid && !BitcoinUnits::parse(currentUnit, text(), 0))
        valid = false;

    setValid(valid);

    return valid;
}

void BitcoinAmountField::setValid(bool valid)
{
    if (valid)
        amount->setStyleSheet("");
    else
        amount->setStyleSheet(STYLE_INVALID);
}

QString BitcoinAmountField::text() const
{
    if (amount->text().isEmpty())
        return QString();
    else
        return amount->text();
}

void BitcoinAmountField::slot_updateTokensList()
{
    if (enableNTP1Tokens) {
        boost::shared_ptr<NTP1Wallet> wallet;
        if (ntp1TokenListModelInstance.load()) {
            wallet = ntp1TokenListModelInstance.load()->getCurrentWallet();
        }

        // update the internal list
        tokenKindsList.clear();
        for (long i = 0; i < wallet->getNumberOfTokens(); i++) {
            NTP1ListElementTokenData d;
            d.fill(i, wallet);
            tokenKindsList.push_back(d);
        }

        std::sort(tokenKindsList.begin(), tokenKindsList.end(),
                  [](const NTP1ListElementTokenData& k1, const NTP1ListElementTokenData& k2) {
                      return k1.name < k2.name;
                  });

        // update the combobox
        tokenKindsComboBox->clear();
        tokenKindsComboBox->addItem(QIcon(QStringLiteral(":/icons/bitcoin")), "NEBL");
        for (unsigned i = 0; i < tokenKindsList.size(); i++) {
            tokenKindsComboBox->addItem(tokenKindsList[i].icon,
                                        tokenKindsList[i].name + " (" +
                                            QString::number(tokenKindsList[i].amount) + ") (" +
                                            tokenKindsList[i].tokenId.left(10) + "...)");
        }
    }
}

void BitcoinAmountField::slot_tokenChanged()
{
    if (enableNTP1Tokens && tokenKindsComboBox->count() > 0) {
        unit->setEnabled(tokenKindsComboBox->currentIndex() == 0);
    }
}

bool BitcoinAmountField::eventFilter(QObject* object, QEvent* event)
{
    if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        if (keyEvent->key() == Qt::Key_Comma) {
            // Translate a comma into a period
            QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".",
                                     keyEvent->isAutoRepeat(), keyEvent->count());
            qApp->sendEvent(object, &periodKeyEvent);
            return true;
        }
    }
    return QWidget::eventFilter(object, event);
}

void BitcoinAmountField::focusInEvent(QFocusEvent*)
{
    // Clear invalid flag on focus
    setValid(true);
}

QWidget* BitcoinAmountField::setupTabChain(QWidget* prev)
{
    QWidget::setTabOrder(prev, amount);
    return amount;
}

qint64 BitcoinAmountField::value(bool* valid_out) const
{
    qint64 val_out = 0;
    bool   valid   = BitcoinUnits::parse(currentUnit, text(), &val_out);
    if (valid_out) {
        *valid_out = valid;
    }
    return val_out;
}

void BitcoinAmountField::setValue(qint64 value) { setText(BitcoinUnits::format(currentUnit, value)); }

QString BitcoinAmountField::getSelectedTokenId() const
{
    if (enableNTP1Tokens && tokenKindsComboBox->count() > 0) {
        int selectedIndex = tokenKindsComboBox->currentIndex();
        if (selectedIndex == 0) {
            return QString::fromStdString(NTP1SendTxData::NEBL_TOKEN_ID);
        } else {
            return tokenKindsList.at(selectedIndex - 1).tokenId; // element 0 is NEBL
        }
    }
    return "";
}

bool BitcoinAmountField::isNTP1TokenSelected() const
{
    return (enableNTP1Tokens && tokenKindsComboBox->currentIndex() != 0);
}

void BitcoinAmountField::unitChanged(int idx)
{
    // Use description tooltip for current unit for the combobox
    unit->setToolTip(unit->itemData(idx, Qt::ToolTipRole).toString());

    // Determine new unit ID
    int newUnit = 0;
    if (!isNTP1TokenSelected()) {
        newUnit = unit->itemData(idx, BitcoinUnits::UnitRole).toInt();
    } else {
        newUnit = static_cast<int>(BitcoinUnit::NTP1);
    }

    // Parse current value and convert to new unit
    bool   valid        = false;
    qint64 currentValue = value(&valid);

    currentUnit = newUnit;

    // Set max length after retrieving the value, to prevent truncation
    amount->setDecimals(BitcoinUnits::decimals(currentUnit));
    amount->setMaximum(qPow(10, BitcoinUnits::amountDigits(currentUnit)) -
                       qPow(10, -amount->decimals()));

    if (valid) {
        // If value was valid, re-place it in the widget with the new unit
        if (!isNTP1TokenSelected()) {
            setValue(currentValue);
        } else {
            setText("");
        }
    } else {
        // If current value is invalid, just clear field
        setText("");
    }
    setValid(true);
}

void BitcoinAmountField::setDisplayUnit(int newUnit) { unit->setValue(newUnit); }
<commit_msg>Fix send token dialog to step up and down with NTP1 tokens<commit_after>#include "bitcoinamountfield.h"
#include "bitcoinunits.h"
#include "ntp1/ntp1listelementtokendata.h"
#include "qvaluecombobox.h"

#include "guiconstants.h"

#include <QApplication>
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QRegExpValidator>
#include <qmath.h>

BitcoinAmountField::BitcoinAmountField(bool EnableNTP1Tokens, QWidget* parent)
    : QWidget(parent), amount(0), currentUnit(-1)
{
    enableNTP1Tokens = EnableNTP1Tokens;

    amount = new QDoubleSpinBox(this);
    amount->setLocale(QLocale::c());
    amount->setDecimals(8);
    amount->installEventFilter(this);
    amount->setMaximumWidth(170);
    amount->setSingleStep(0.001);

    QHBoxLayout* layout = new QHBoxLayout(this);
    layout->addWidget(amount);
    unit = new QValueComboBox(this);
    unit->setModel(new BitcoinUnits(this));
    layout->addWidget(unit);
    //    layout->addStretch(1);
    layout->setContentsMargins(0, 0, 0, 0);

    if (enableNTP1Tokens) {
        tokenKindsComboBox = new QComboBox;
        tokenKindsComboBox->addItem(QIcon(QStringLiteral(":/icons/bitcoin")), "NEBL");
        layout->addWidget(tokenKindsComboBox);

        refreshTokensButton = new QToolButton;
        QIcon icon;
        icon.addFile(QStringLiteral(":/icons/refresh"), QSize(), QIcon::Normal, QIcon::Off);
        refreshTokensButton->setIcon(icon);
        refreshTokensButton->setToolTip("Refresh tokens list");
        layout->addWidget(refreshTokensButton);

        connect(refreshTokensButton, &QToolButton::clicked, this,
                &BitcoinAmountField::slot_updateTokensList);
        connect(tokenKindsComboBox,
                static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
                &BitcoinAmountField::slot_tokenChanged);
    }

    setLayout(layout);

    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(amount);

    // If one if the widgets changes, the combined content changes as well
    connect(amount, SIGNAL(valueChanged(QString)), this, SIGNAL(textChanged()));
    connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));
    if (enableNTP1Tokens) {
        connect(tokenKindsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));
    }

    // Set default based on configuration
    unitChanged(unit->currentIndex());
}

void BitcoinAmountField::setText(const QString& text)
{
    if (text.isEmpty())
        amount->clear();
    else
        amount->setValue(text.toDouble());
}

void BitcoinAmountField::clear()
{
    amount->clear();
    unit->setCurrentIndex(0);
    if (enableNTP1Tokens) {
        tokenKindsComboBox->setCurrentIndex(0);
        slot_updateTokensList();
    }
}

bool BitcoinAmountField::validate()
{
    bool valid = true;
    if (amount->value() == 0.0)
        valid = false;
    if (valid && !BitcoinUnits::parse(currentUnit, text(), 0))
        valid = false;

    setValid(valid);

    return valid;
}

void BitcoinAmountField::setValid(bool valid)
{
    if (valid)
        amount->setStyleSheet("");
    else
        amount->setStyleSheet(STYLE_INVALID);
}

QString BitcoinAmountField::text() const
{
    if (amount->text().isEmpty())
        return QString();
    else
        return amount->text();
}

void BitcoinAmountField::slot_updateTokensList()
{
    if (enableNTP1Tokens) {
        boost::shared_ptr<NTP1Wallet> wallet;
        if (ntp1TokenListModelInstance.load()) {
            wallet = ntp1TokenListModelInstance.load()->getCurrentWallet();
        }

        // update the internal list
        tokenKindsList.clear();
        for (long i = 0; i < wallet->getNumberOfTokens(); i++) {
            NTP1ListElementTokenData d;
            d.fill(i, wallet);
            tokenKindsList.push_back(d);
        }

        std::sort(tokenKindsList.begin(), tokenKindsList.end(),
                  [](const NTP1ListElementTokenData& k1, const NTP1ListElementTokenData& k2) {
                      return k1.name < k2.name;
                  });

        // update the combobox
        tokenKindsComboBox->clear();
        tokenKindsComboBox->addItem(QIcon(QStringLiteral(":/icons/bitcoin")), "NEBL");
        for (unsigned i = 0; i < tokenKindsList.size(); i++) {
            tokenKindsComboBox->addItem(tokenKindsList[i].icon,
                                        tokenKindsList[i].name + " (" +
                                            QString::number(tokenKindsList[i].amount) + ") (" +
                                            tokenKindsList[i].tokenId.left(10) + "...)");
        }
    }
}

void BitcoinAmountField::slot_tokenChanged()
{
    if (enableNTP1Tokens && tokenKindsComboBox->count() > 0) {
        unit->setEnabled(tokenKindsComboBox->currentIndex() == 0);
        if (isNTP1TokenSelected()) {
            amount->setSingleStep(1);
        } else {
            amount->setSingleStep(0.001);
        }
    }
}

bool BitcoinAmountField::eventFilter(QObject* object, QEvent* event)
{
    if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        if (keyEvent->key() == Qt::Key_Comma) {
            // Translate a comma into a period
            QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".",
                                     keyEvent->isAutoRepeat(), keyEvent->count());
            qApp->sendEvent(object, &periodKeyEvent);
            return true;
        }
    }
    return QWidget::eventFilter(object, event);
}

void BitcoinAmountField::focusInEvent(QFocusEvent*)
{
    // Clear invalid flag on focus
    setValid(true);
}

QWidget* BitcoinAmountField::setupTabChain(QWidget* prev)
{
    QWidget::setTabOrder(prev, amount);
    return amount;
}

qint64 BitcoinAmountField::value(bool* valid_out) const
{
    qint64 val_out = 0;
    bool   valid   = BitcoinUnits::parse(currentUnit, text(), &val_out);
    if (valid_out) {
        *valid_out = valid;
    }
    return val_out;
}

void BitcoinAmountField::setValue(qint64 value) { setText(BitcoinUnits::format(currentUnit, value)); }

QString BitcoinAmountField::getSelectedTokenId() const
{
    if (enableNTP1Tokens && tokenKindsComboBox->count() > 0) {
        int selectedIndex = tokenKindsComboBox->currentIndex();
        if (selectedIndex == 0) {
            return QString::fromStdString(NTP1SendTxData::NEBL_TOKEN_ID);
        } else {
            return tokenKindsList.at(selectedIndex - 1).tokenId; // element 0 is NEBL
        }
    }
    return "";
}

bool BitcoinAmountField::isNTP1TokenSelected() const
{
    return (enableNTP1Tokens && tokenKindsComboBox->currentIndex() != 0);
}

void BitcoinAmountField::unitChanged(int idx)
{
    // Use description tooltip for current unit for the combobox
    unit->setToolTip(unit->itemData(idx, Qt::ToolTipRole).toString());

    // Determine new unit ID
    int newUnit = 0;
    if (!isNTP1TokenSelected()) {
        newUnit = unit->itemData(idx, BitcoinUnits::UnitRole).toInt();
    } else {
        newUnit = static_cast<int>(BitcoinUnit::NTP1);
    }

    // Parse current value and convert to new unit
    bool   valid        = false;
    qint64 currentValue = value(&valid);

    currentUnit = newUnit;

    // Set max length after retrieving the value, to prevent truncation
    amount->setDecimals(BitcoinUnits::decimals(currentUnit));
    amount->setMaximum(qPow(10, BitcoinUnits::amountDigits(currentUnit)) -
                       qPow(10, -amount->decimals()));

    if (valid) {
        // If value was valid, re-place it in the widget with the new unit
        if (!isNTP1TokenSelected()) {
            setValue(currentValue);
        } else {
            setText("");
        }
    } else {
        // If current value is invalid, just clear field
        setText("");
    }
    setValid(true);
}

void BitcoinAmountField::setDisplayUnit(int newUnit) { unit->setValue(newUnit); }
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS)
 *
 * This file is part of metaverse.
 *
 * metaverse 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/>.
 */
#ifndef MVS_DATABASE_DATA_BASE_HPP
#define MVS_DATABASE_DATA_BASE_HPP

#include <atomic>
#include <cstddef>
#include <memory>
#include <boost/filesystem.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <metaverse/bitcoin.hpp>
#include <metaverse/database/databases/block_database.hpp>
#include <metaverse/database/databases/spend_database.hpp>
#include <metaverse/database/databases/transaction_database.hpp>
#include <metaverse/database/databases/history_database.hpp>
#include <metaverse/database/databases/stealth_database.hpp>
#include <metaverse/database/define.hpp>
#include <metaverse/database/settings.hpp>

#include <boost/variant.hpp>
#include <metaverse/bitcoin/chain/attachment/asset/asset.hpp>
#include <metaverse/bitcoin/chain/attachment/etp/etp.hpp>
#include <metaverse/bitcoin/chain/attachment/message/message.hpp>
#include <metaverse/bitcoin/chain/attachment/account/account.hpp>
#include <metaverse/bitcoin/chain/attachment/asset/asset_detail.hpp>
#include <metaverse/bitcoin/chain/attachment/asset/asset_transfer.hpp>
#include <metaverse/bitcoin/chain/attachment/attachment.hpp>

#include <metaverse/database/databases/account_database.hpp>
#include <metaverse/database/databases/account_address_database.hpp>
#include <metaverse/database/databases/asset_database.hpp>
#include <metaverse/database/databases/blockchain_asset_database.hpp>
#include <metaverse/database/databases/address_asset_database.hpp>
#include <metaverse/database/databases/account_asset_database.hpp>
//#include <metaverse/bitcoin/wallet/payment_address.hpp>
#define  LOG_DATABASE  "database"  // for log_debug output

using namespace libbitcoin::wallet;
using namespace libbitcoin::chain;

namespace libbitcoin {
namespace database {

typedef uint64_t handle;

class BCD_API data_base
{
public:
    typedef boost::filesystem::path path;

    class store
    {
    public:
        store(const path& prefix);
        bool touch_all() const;

        path database_lock;
        path blocks_lookup;
        path blocks_index;
        path history_lookup;
        path history_rows;
        path stealth_rows;
        path spends_lookup;
        path transactions_lookup;
		/* begin database for account, asset, address_asset relationship */
        path accounts_lookup;
        path assets_lookup;
        path address_assets_lookup;
        path address_assets_rows;
        path account_assets_lookup;
        path account_assets_rows;
        path account_addresses_lookup;
        path account_addresses_rows;
		/* end database for account, asset, address_asset relationship */
    };

    class blockchain_store
    {
    public:
        blockchain_store(const path& prefix);
        bool touch_all() const;

        path database_lock;
        path blocks_lookup;
        path blocks_index;
        path history_lookup;
        path history_rows;
        path stealth_rows;
        path spends_lookup;
        path transactions_lookup;
		/* begin database for account, asset, address_asset relationship */
        path assets_lookup;
        path address_assets_lookup;
        path address_assets_rows;
		/* end database for account, asset, address_asset relationship */
    };

    class blockchain_asset_store
    {
    public:
        blockchain_asset_store(const path& prefix);
        bool touch_all() const;
		/* begin database for account, asset, address_asset relationship */
        path assets_lookup;
		/* end database for account, asset, address_asset relationship */
    };
	class db_metadata
	{
	public:
		db_metadata();
		db_metadata(std::string version);
		void reset();
		bool from_data(const data_chunk& data);
		bool from_data(std::istream& stream);
		bool from_data(reader& source);
		data_chunk to_data() const;
		void to_data(std::ostream& stream) const;
		void to_data(writer& sink) const;
		uint64_t serialized_size() const;

#ifdef MVS_DEBUG
		std::string to_string() const;
#endif
		friend std::istream& operator>>(std::istream& input, db_metadata& metadata);
		friend std::ostream& operator<<(std::ostream& output, const db_metadata& metadata);
		static const std::string current_version;
		static const std::string file_name;

		std::string version_;
	};

    /// Create a new database file with a given path prefix and default paths.
    static bool initialize(const path& prefix, const chain::block& genesis);
    static bool touch_file(const path& file_path);
	static void write_metadata(const path& metadata_path, data_base::db_metadata& metadata);
	static void read_metadata(const path& metadata_path, data_base::db_metadata& metadata);
	static bool is_lower_database(const path& prefix);
	static bool is_higher_database(const path& prefix);
	static bool upgrade_database(const settings& settings, const chain::block& genesis);
    /// Construct all databases.
    data_base(const settings& settings);

    /// Stop all databases (threads must be joined).
    ~data_base();
	bool clear_block_db();
    // Startup and shutdown.
    // ------------------------------------------------------------------------

    /// Create and start all databases.
    bool create();
	bool blockchain_create();
	bool blockchain_asset_create();

	void upgrade_blockchain_asset();
	bool account_db_start();
    /// Start all databases.
    bool start();

    /// Signal all databases to stop work.
    bool stop();

    /// Stop all databases (threads must be joined).
    bool close();

    // Locking.
    // ------------------------------------------------------------------------

    handle begin_read();
    bool begin_write();
    bool end_write();
    bool is_read_valid(handle handle);
    bool is_write_locked(handle handle);

    // Push and pop.
    // ------------------------------------------------------------------------

    /// Commit block at next height with indexing and no duplicate protection.
    void push(const chain::block& block);

    /// Commit block at given height with indexing and no duplicate protection.
    /// If height is not count + 1 then the count will not equal top height.
    void push(const chain::block& block, uint64_t height);

    /// Throws if the chain is empty.
    chain::block pop();

    /* begin store asset info into  database */

	void push_attachemnt(const attachment& attach, const payment_address& address,
			const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_etp(const etp& etp, const short_hash& key,
			const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_etp_award(const etp_award& etp, const short_hash& key,
			const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_message(const chain::blockchain_message& msg, const short_hash& key,
			const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_asset(const asset& sp, const short_hash& key,
				const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_asset_detail(const asset_detail& sp_detail, const short_hash& key,
				const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_asset_transfer(const asset_transfer& sp_transfer, const short_hash& key,
				const output_point& outpoint, uint32_t output_height, uint64_t value);

   class attachment_visitor : public boost::static_visitor<void>
	{
	public:
		attachment_visitor(data_base* db, const short_hash& sh_hash,  const output_point& outpoint,
			uint32_t output_height, uint64_t value):
			db_(db), sh_hash_(sh_hash), outpoint_(outpoint), output_height_(output_height), value_(value)
		{

		}
		void operator()(const asset &t) const
		{
			return db_->push_asset(t, sh_hash_, outpoint_, output_height_, value_);
		}
		void operator()(const etp &t) const
		{
			return db_->push_etp(t, sh_hash_, outpoint_, output_height_, value_);
		}
		void operator()(const etp_award &t) const
		{
			return db_->push_etp_award(t, sh_hash_, outpoint_, output_height_, value_);
		}
		void operator()(const chain::blockchain_message &t) const
		{
			return db_->push_message(t, sh_hash_, outpoint_, output_height_, value_);
		}
	private:
        data_base* db_;
		short_hash sh_hash_;
		output_point outpoint_;
		uint32_t output_height_;
		uint64_t value_;
	};

	class asset_visitor : public boost::static_visitor<void>
	{
	public:
		asset_visitor(data_base* db, const short_hash& key,
			const output_point& outpoint, uint32_t output_height, uint64_t value):
			db_(db), key_(key), outpoint_(outpoint), output_height_(output_height), value_(value)
		{

		}
		void operator()(const asset_detail &t) const
		{
			return db_->push_asset_detail(t, key_, outpoint_, output_height_, value_);
		}
		void operator()(const asset_transfer &t) const
		{
		 	return db_->push_asset_transfer(t, key_, outpoint_, output_height_, value_);
		}
	private:
        data_base* db_;
		short_hash key_;
		output_point outpoint_;
		uint32_t output_height_;
		uint64_t value_;
	};
	void set_admin(const std::string& name, const std::string& passwd);
   /* begin store asset info into  database */

protected:
    data_base(const store& paths, size_t history_height, size_t stealth_height);
    data_base(const path& prefix, size_t history_height, size_t stealth_height);

private:
    typedef chain::input::list inputs;
    typedef chain::output::list outputs;
    typedef std::atomic<size_t> sequential_lock;
    typedef boost::interprocess::file_lock file_lock;

    static void uninitialize_lock(const path& lock);
    static file_lock initialize_lock(const path& lock);

    void synchronize();
    void push_inputs(const hash_digest& tx_hash, size_t height,
        const inputs& inputs);
    void push_outputs(const hash_digest& tx_hash, size_t height,
        const outputs& outputs);
    void push_stealth(const hash_digest& tx_hash, size_t height,
        const outputs& outputs);
    void pop_inputs(const inputs& inputs, size_t height);
    void pop_outputs(const outputs& outputs, size_t height);

    const path lock_file_path_;
    const size_t history_height_;
    const size_t stealth_height_;

    // Atomic counter for implementing the sequential lock pattern.
    sequential_lock sequential_lock_;

    // Allows us to restrict database access to our process (or fail).
    std::shared_ptr<file_lock> file_lock_;

    // Cross-database mutext to prevent concurrent file remapping.
    std::shared_ptr<shared_mutex> mutex_;

	// temp block timestamp
	uint32_t timestamp_;

public:

    /// Individual database query engines.
    block_database blocks;
    history_database history;
    spend_database spends;
    stealth_database stealth;
    transaction_database transactions;
	/* begin database for account, asset, address_asset relationship */
    account_database accounts;
    //asset_database assets;
    blockchain_asset_database assets;
    address_asset_database address_assets;
    account_asset_database account_assets;
    account_address_database account_addresses;
	/* end database for account, asset, address_asset relationship */
};

} // namespace database
} // namespace libbitcoin

#endif

<commit_msg>get rid of duplicate LOG_DATABASE macro definition<commit_after>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS)
 *
 * This file is part of metaverse.
 *
 * metaverse 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/>.
 */
#ifndef MVS_DATABASE_DATA_BASE_HPP
#define MVS_DATABASE_DATA_BASE_HPP

#include <atomic>
#include <cstddef>
#include <memory>
#include <boost/filesystem.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <metaverse/bitcoin.hpp>
#include <metaverse/database/databases/block_database.hpp>
#include <metaverse/database/databases/spend_database.hpp>
#include <metaverse/database/databases/transaction_database.hpp>
#include <metaverse/database/databases/history_database.hpp>
#include <metaverse/database/databases/stealth_database.hpp>
#include <metaverse/database/define.hpp>
#include <metaverse/database/settings.hpp>

#include <boost/variant.hpp>
#include <metaverse/bitcoin/chain/attachment/asset/asset.hpp>
#include <metaverse/bitcoin/chain/attachment/etp/etp.hpp>
#include <metaverse/bitcoin/chain/attachment/message/message.hpp>
#include <metaverse/bitcoin/chain/attachment/account/account.hpp>
#include <metaverse/bitcoin/chain/attachment/asset/asset_detail.hpp>
#include <metaverse/bitcoin/chain/attachment/asset/asset_transfer.hpp>
#include <metaverse/bitcoin/chain/attachment/attachment.hpp>

#include <metaverse/database/databases/account_database.hpp>
#include <metaverse/database/databases/account_address_database.hpp>
#include <metaverse/database/databases/asset_database.hpp>
#include <metaverse/database/databases/blockchain_asset_database.hpp>
#include <metaverse/database/databases/address_asset_database.hpp>
#include <metaverse/database/databases/account_asset_database.hpp>

using namespace libbitcoin::wallet;
using namespace libbitcoin::chain;

namespace libbitcoin {
namespace database {

typedef uint64_t handle;

class BCD_API data_base
{
public:
    typedef boost::filesystem::path path;

    class store
    {
    public:
        store(const path& prefix);
        bool touch_all() const;

        path database_lock;
        path blocks_lookup;
        path blocks_index;
        path history_lookup;
        path history_rows;
        path stealth_rows;
        path spends_lookup;
        path transactions_lookup;
		/* begin database for account, asset, address_asset relationship */
        path accounts_lookup;
        path assets_lookup;
        path address_assets_lookup;
        path address_assets_rows;
        path account_assets_lookup;
        path account_assets_rows;
        path account_addresses_lookup;
        path account_addresses_rows;
		/* end database for account, asset, address_asset relationship */
    };

    class blockchain_store
    {
    public:
        blockchain_store(const path& prefix);
        bool touch_all() const;

        path database_lock;
        path blocks_lookup;
        path blocks_index;
        path history_lookup;
        path history_rows;
        path stealth_rows;
        path spends_lookup;
        path transactions_lookup;
		/* begin database for account, asset, address_asset relationship */
        path assets_lookup;
        path address_assets_lookup;
        path address_assets_rows;
		/* end database for account, asset, address_asset relationship */
    };

    class blockchain_asset_store
    {
    public:
        blockchain_asset_store(const path& prefix);
        bool touch_all() const;
		/* begin database for account, asset, address_asset relationship */
        path assets_lookup;
		/* end database for account, asset, address_asset relationship */
    };
	class db_metadata
	{
	public:
		db_metadata();
		db_metadata(std::string version);
		void reset();
		bool from_data(const data_chunk& data);
		bool from_data(std::istream& stream);
		bool from_data(reader& source);
		data_chunk to_data() const;
		void to_data(std::ostream& stream) const;
		void to_data(writer& sink) const;
		uint64_t serialized_size() const;

#ifdef MVS_DEBUG
		std::string to_string() const;
#endif
		friend std::istream& operator>>(std::istream& input, db_metadata& metadata);
		friend std::ostream& operator<<(std::ostream& output, const db_metadata& metadata);
		static const std::string current_version;
		static const std::string file_name;

		std::string version_;
	};

    /// Create a new database file with a given path prefix and default paths.
    static bool initialize(const path& prefix, const chain::block& genesis);
    static bool touch_file(const path& file_path);
	static void write_metadata(const path& metadata_path, data_base::db_metadata& metadata);
	static void read_metadata(const path& metadata_path, data_base::db_metadata& metadata);
	static bool is_lower_database(const path& prefix);
	static bool is_higher_database(const path& prefix);
	static bool upgrade_database(const settings& settings, const chain::block& genesis);
    /// Construct all databases.
    data_base(const settings& settings);

    /// Stop all databases (threads must be joined).
    ~data_base();
	bool clear_block_db();
    // Startup and shutdown.
    // ------------------------------------------------------------------------

    /// Create and start all databases.
    bool create();
	bool blockchain_create();
	bool blockchain_asset_create();

	void upgrade_blockchain_asset();
	bool account_db_start();
    /// Start all databases.
    bool start();

    /// Signal all databases to stop work.
    bool stop();

    /// Stop all databases (threads must be joined).
    bool close();

    // Locking.
    // ------------------------------------------------------------------------

    handle begin_read();
    bool begin_write();
    bool end_write();
    bool is_read_valid(handle handle);
    bool is_write_locked(handle handle);

    // Push and pop.
    // ------------------------------------------------------------------------

    /// Commit block at next height with indexing and no duplicate protection.
    void push(const chain::block& block);

    /// Commit block at given height with indexing and no duplicate protection.
    /// If height is not count + 1 then the count will not equal top height.
    void push(const chain::block& block, uint64_t height);

    /// Throws if the chain is empty.
    chain::block pop();

    /* begin store asset info into  database */

	void push_attachemnt(const attachment& attach, const payment_address& address,
			const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_etp(const etp& etp, const short_hash& key,
			const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_etp_award(const etp_award& etp, const short_hash& key,
			const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_message(const chain::blockchain_message& msg, const short_hash& key,
			const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_asset(const asset& sp, const short_hash& key,
				const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_asset_detail(const asset_detail& sp_detail, const short_hash& key,
				const output_point& outpoint, uint32_t output_height, uint64_t value);

	void push_asset_transfer(const asset_transfer& sp_transfer, const short_hash& key,
				const output_point& outpoint, uint32_t output_height, uint64_t value);

   class attachment_visitor : public boost::static_visitor<void>
	{
	public:
		attachment_visitor(data_base* db, const short_hash& sh_hash,  const output_point& outpoint,
			uint32_t output_height, uint64_t value):
			db_(db), sh_hash_(sh_hash), outpoint_(outpoint), output_height_(output_height), value_(value)
		{

		}
		void operator()(const asset &t) const
		{
			return db_->push_asset(t, sh_hash_, outpoint_, output_height_, value_);
		}
		void operator()(const etp &t) const
		{
			return db_->push_etp(t, sh_hash_, outpoint_, output_height_, value_);
		}
		void operator()(const etp_award &t) const
		{
			return db_->push_etp_award(t, sh_hash_, outpoint_, output_height_, value_);
		}
		void operator()(const chain::blockchain_message &t) const
		{
			return db_->push_message(t, sh_hash_, outpoint_, output_height_, value_);
		}
	private:
        data_base* db_;
		short_hash sh_hash_;
		output_point outpoint_;
		uint32_t output_height_;
		uint64_t value_;
	};

	class asset_visitor : public boost::static_visitor<void>
	{
	public:
		asset_visitor(data_base* db, const short_hash& key,
			const output_point& outpoint, uint32_t output_height, uint64_t value):
			db_(db), key_(key), outpoint_(outpoint), output_height_(output_height), value_(value)
		{

		}
		void operator()(const asset_detail &t) const
		{
			return db_->push_asset_detail(t, key_, outpoint_, output_height_, value_);
		}
		void operator()(const asset_transfer &t) const
		{
		 	return db_->push_asset_transfer(t, key_, outpoint_, output_height_, value_);
		}
	private:
        data_base* db_;
		short_hash key_;
		output_point outpoint_;
		uint32_t output_height_;
		uint64_t value_;
	};
	void set_admin(const std::string& name, const std::string& passwd);
   /* begin store asset info into  database */

protected:
    data_base(const store& paths, size_t history_height, size_t stealth_height);
    data_base(const path& prefix, size_t history_height, size_t stealth_height);

private:
    typedef chain::input::list inputs;
    typedef chain::output::list outputs;
    typedef std::atomic<size_t> sequential_lock;
    typedef boost::interprocess::file_lock file_lock;

    static void uninitialize_lock(const path& lock);
    static file_lock initialize_lock(const path& lock);

    void synchronize();
    void push_inputs(const hash_digest& tx_hash, size_t height,
        const inputs& inputs);
    void push_outputs(const hash_digest& tx_hash, size_t height,
        const outputs& outputs);
    void push_stealth(const hash_digest& tx_hash, size_t height,
        const outputs& outputs);
    void pop_inputs(const inputs& inputs, size_t height);
    void pop_outputs(const outputs& outputs, size_t height);

    const path lock_file_path_;
    const size_t history_height_;
    const size_t stealth_height_;

    // Atomic counter for implementing the sequential lock pattern.
    sequential_lock sequential_lock_;

    // Allows us to restrict database access to our process (or fail).
    std::shared_ptr<file_lock> file_lock_;

    // Cross-database mutext to prevent concurrent file remapping.
    std::shared_ptr<shared_mutex> mutex_;

	// temp block timestamp
	uint32_t timestamp_;

public:

    /// Individual database query engines.
    block_database blocks;
    history_database history;
    spend_database spends;
    stealth_database stealth;
    transaction_database transactions;
	/* begin database for account, asset, address_asset relationship */
    account_database accounts;
    //asset_database assets;
    blockchain_asset_database assets;
    address_asset_database address_assets;
    account_asset_database account_assets;
    account_address_database account_addresses;
	/* end database for account, asset, address_asset relationship */
};

} // namespace database
} // namespace libbitcoin

#endif

<|endoftext|>


<commit_before>#include "common.h"

/**
 * Initialises peripherials
 * @param emu   Reference to the emulator structure
 */
Peripheral::Peripheral(Emulator &emu)
  : emu(emu)
  , spi1_enable(false)
  , spi2_enable(false)
  , irq_tx(false)
  , irq_rx(false)
  , uart_enable(false)
  , uart_bits(7)
  , uart_dlab(0)
{ }

/**
 * Handles a write to a peripherial register
 * @param addr  Port number
 * @param data  Data received
 */
void Peripheral::writePort(uint32_t addr, uint8_t data)
{
  switch (addr)
  {
    case AUX_ENABLES:
    {
      /* Enables / disables peripherials */
      uart_enable = (data & 0x1) != 0;
      spi1_enable = (data & 0x2) != 0;
      spi2_enable = (data & 0x4) != 0;
      return;
    }
    case AUX_MU_IER_REG:
    {
      if (uart_dlab)
      {
        /* MSB of baud rate register */
        uart_baud_rate = (uart_baud_rate & 0xFF) | ((data >> 8) & 0xFF);
      }
      else
      {
        /* Enables / disables interrupts */
        irq_rx = (data & 0x1) != 0;
        irq_tx = (data & 0x1) != 0;
      }
      return;
    }
    case AUX_MU_LCR_REG:
    {
      /* TODO: implement other bits */
      uart_bits = data & 0x1 ? 8 : 7;
      return;
    }
    case AUX_MU_BAUD_REG:
    {
      uart_baud_rate_counter = data & 0xFF;
      return;
    }
    case AUX_MU_IO_REG:
    {
      if (uart_dlab)
      {
        /* LSB of baud rate register */
        uart_baud_rate = (uart_baud_rate & 0xFF00) | (data & 0xFF);
      }
      else
      {
        /* Dump output to stdout */
        emu.info("%c", data & 0xFF);
      }
      return;
    }
  }

  emu.error("Unsupported peripherial write: %08x", addr);
}

/**
 * Handles a read from a peripherial port
 * @param addr Port address
 * @return     Read value
 */
uint32_t Peripheral::readPort(uint32_t addr)
{
  switch (addr)
  {
    case AUX_ENABLES:
    {
      /* Returns a bitmask of enabled peripherials */
      return (uart_enable ? 0x1 : 0x0) |
             (spi1_enable ? 0x2 : 0x0) |
             (spi2_enable ? 0x4 : 0x0);
    }
    case AUX_MU_IER_REG:
    {
      /* Returns a bitmask of interrupt status */
      return (irq_rx ? 0x1 : 0x0) |
             (irq_tx ? 0x2 : 0x0);
    }
    case AUX_MU_LSR_REG:
    {
      /* Transmitter always ready */
      return 0x60;
    }
    case AUX_MU_IO_REG:
    {
      if (uart_dlab)
      {
        /* LSB of baud rate register */
        return uart_baud_rate & 0xFF;
      }
      else
      {
        /* Always read 0 */
        return 0x00;
      }
    }
  }

  emu.error("Unsupported peripherial read: %08x", addr);
  return 0;
}

<commit_msg>irq_tx uses bit 2<commit_after>#include "common.h"

/**
 * Initialises peripherials
 * @param emu   Reference to the emulator structure
 */
Peripheral::Peripheral(Emulator &emu)
  : emu(emu)
  , spi1_enable(false)
  , spi2_enable(false)
  , irq_tx(false)
  , irq_rx(false)
  , uart_enable(false)
  , uart_bits(7)
  , uart_dlab(0)
{ }

/**
 * Handles a write to a peripherial register
 * @param addr  Port number
 * @param data  Data received
 */
void Peripheral::writePort(uint32_t addr, uint8_t data)
{
  switch (addr)
  {
    case AUX_ENABLES:
    {
      /* Enables / disables peripherials */
      uart_enable = (data & 0x1) != 0;
      spi1_enable = (data & 0x2) != 0;
      spi2_enable = (data & 0x4) != 0;
      return;
    }
    case AUX_MU_IER_REG:
    {
      if (uart_dlab)
      {
        /* MSB of baud rate register */
        uart_baud_rate = (uart_baud_rate & 0xFF) | ((data >> 8) & 0xFF);
      }
      else
      {
        /* Enables / disables interrupts */
        irq_rx = (data & 0x1) != 0;
        irq_tx = (data & 0x2) != 0;
      }
      return;
    }
    case AUX_MU_LCR_REG:
    {
      /* TODO: implement other bits */
      uart_bits = data & 0x1 ? 8 : 7;
      return;
    }
    case AUX_MU_BAUD_REG:
    {
      uart_baud_rate_counter = data & 0xFF;
      return;
    }
    case AUX_MU_IO_REG:
    {
      if (uart_dlab)
      {
        /* LSB of baud rate register */
        uart_baud_rate = (uart_baud_rate & 0xFF00) | (data & 0xFF);
      }
      else
      {
        /* Dump output to stdout */
        emu.info("%c", data & 0xFF);
      }
      return;
    }
  }

  emu.error("Unsupported peripherial write: %08x", addr);
}

/**
 * Handles a read from a peripherial port
 * @param addr Port address
 * @return     Read value
 */
uint32_t Peripheral::readPort(uint32_t addr)
{
  switch (addr)
  {
    case AUX_ENABLES:
    {
      /* Returns a bitmask of enabled peripherials */
      return (uart_enable ? 0x1 : 0x0) |
             (spi1_enable ? 0x2 : 0x0) |
             (spi2_enable ? 0x4 : 0x0);
    }
    case AUX_MU_IER_REG:
    {
      /* Returns a bitmask of interrupt status */
      return (irq_rx ? 0x1 : 0x0) |
             (irq_tx ? 0x2 : 0x0);
    }
    case AUX_MU_LSR_REG:
    {
      /* Transmitter always ready */
      return 0x60;
    }
    case AUX_MU_IO_REG:
    {
      if (uart_dlab)
      {
        /* LSB of baud rate register */
        return uart_baud_rate & 0xFF;
      }
      else
      {
        /* Always read 0 */
        return 0x00;
      }
    }
  }

  emu.error("Unsupported peripherial read: %08x", addr);
  return 0;
}

<|endoftext|>


<commit_before>///
/// @file   littleendian_cast.hpp
/// @brief  Cast bytes in ascending address order on both little and
///         big endian CPUs.
///
/// Copyright (C) 2013 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef LITTLEENDIAN_CAST_HPP
#define LITTLEENDIAN_CAST_HPP

#include "config.hpp"

namespace primesieve {

/// http://c-faq.com/misc/endiantest.html
inline bool is_littleendian()
{
  union {
    int word;
    char c[sizeof(int)];
  } x;
  x.word = 1;
  return (x.c[0] == 1);
}

/// Recursively sum bytes using template metaprogramming.
/// e.g. littleendian_cast<int32_t>(array) =
/// return (array[0] <<  0) +
///        (array[1] <<  8) +
///        (array[2] << 16) +
///        (array[3] << 24);
///
template <typename T, int INDEX, int STOP>
struct littleendian_cast_helper
{
  static T sum(const byte_t* array, T n)
  {
    n += static_cast<T>(array[INDEX]) << (INDEX * 8);
    return littleendian_cast_helper<T, INDEX + 1, STOP - 1>::sum(array, n);
  }
};

template <typename T, int INDEX>
struct littleendian_cast_helper<T, INDEX, 0>
{
  static T sum(const byte_t*, T n)
  {
    return n;
  }
};

template <typename T>
inline T littleendian_cast(const byte_t* array)
{
  if (is_littleendian())
    return *reinterpret_cast<const T*>(array);
  return littleendian_cast_helper<T, 0, sizeof(T)>::sum(array, 0);
}

} // namespace primesieve

#endif
<commit_msg>Update comment<commit_after>///
/// @file   littleendian_cast.hpp
/// @brief  Cast bytes in ascending address order on both little and
///         big endian CPUs.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef LITTLEENDIAN_CAST_HPP
#define LITTLEENDIAN_CAST_HPP

#include "config.hpp"

namespace primesieve {

/// http://c-faq.com/misc/endiantest.html
inline bool is_littleendian()
{
  union {
    int word;
    char c[sizeof(int)];
  } x;
  x.word = 1;
  return (x.c[0] == 1);
}

/// Recursively sum bytes using template metaprogramming.
/// e.g. littleendian_cast<int32_t>(array) =
/// return (array[0] <<  0) +
///        (array[1] <<  8) +
///        (array[2] << 16) +
///        (array[3] << 24);
///
template <typename T, int INDEX, int STOP>
struct littleendian_cast_helper
{
  static T sum(const byte_t* array, T n)
  {
    n += static_cast<T>(array[INDEX]) << (INDEX * 8);
    return littleendian_cast_helper<T, INDEX + 1, STOP - 1>::sum(array, n);
  }
};

template <typename T, int INDEX>
struct littleendian_cast_helper<T, INDEX, 0>
{
  static T sum(const byte_t*, T n)
  {
    return n;
  }
};

template <typename T>
inline T littleendian_cast(const byte_t* array)
{
  if (is_littleendian())
    return *reinterpret_cast<const T*>(array);
  return littleendian_cast_helper<T, 0, sizeof(T)>::sum(array, 0);
}

} // namespace

#endif
<|endoftext|>


<commit_before>#pragma once

#include <mutex>

/*!
 * Namespace indents were made intentionally to improve the readability.
 */
namespace blackhole {
    namespace repository {
        namespace config {
            template<class T>
            struct transformer_t;

            template<class To>
            class parser_t;
        } // namespace config
    } // namespace repository

    namespace attribute {
        class set_view_t;
        class combined_view_t;
    } // namespace attribute

    class base_frontend_t;
    class frontend_factory_t;

    class formatter_config_t;
    class sink_config_t;

    class scoped_attributes_concept_t;

    class record_t;

    class logger_base_t;

    template<typename Level>
    class verbose_logger_t;

    template<class Logger, class = void>
    class wrapper_t;

    template<class T, class Mutex = std::mutex>
    class synchronized;
} // namespace blackhole
<commit_msg>[Detail] More forwards.<commit_after>#pragma once

#include <mutex>

/*!
 * Namespace indents were made intentionally to improve the readability.
 */
namespace blackhole {
    namespace repository {
        namespace config {
            template<class T>
            struct transformer_t;

            template<class To>
            class parser_t;
        } // namespace config
    } // namespace repository

    namespace attribute {
        class set_view_t;
        class combined_view_t;
    } // namespace attribute

    class base_frontend_t;
    class frontend_factory_t;

    class formatter_config_t;
    class sink_config_t;

    class scoped_attributes_concept_t;

    class record_t;

    class base_logger_t;
    class logger_base_t;

    template<typename Level>
    class verbose_logger_t;

    template<class Logger, class = void>
    class wrapper_t;

    template<class T, class Mutex = std::mutex>
    class synchronized;
} // namespace blackhole
<|endoftext|>