<commit_before>/*
 * SchemeShell.cc
 *
 * Simple scheme shell
 * Copyright (c) 2008 Linas Vepstas <linas@linas.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 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, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifdef HAVE_GUILE

#include <opencog/util/Config.h>
#include <opencog/util/Logger.h>
#include <opencog/guile/SchemeEval.h>
#include <opencog/cogserver/server/ConsoleSocket.h>
#include <opencog/cogserver/server/CogServer.h>

#include "SchemeShell.h"

using namespace opencog;

SchemeShell::SchemeShell(void)
{
	normal_prompt = "guile> ";
	if (config().get_bool("ANSI_ENABLED"))
		normal_prompt = config()["ANSI_SCM_PROMPT"];
	else
		normal_prompt = config()["SCM_PROMPT"];

	abort_prompt += normal_prompt;

	pending_prompt = "... ";

	evaluator = SchemeEval::get_evaluator();

	// Set the inital atomspace for this thread.
	SchemeEval::set_scheme_as(&cogserver().getAtomSpace());
	evaluator->begin_eval();
	evaluator->eval_expr("(setlocale LC_CTYPE \"\")");
	evaluator->poll_result();
}

SchemeShell::~SchemeShell()
{
}

/**
 * Register this shell with the console.
 */
void SchemeShell::thread_init(void)
{
	SchemeEval::set_scheme_as(&cogserver().getAtomSpace());
}

#endif
/* ===================== END OF FILE ============================ */
<commit_msg>Skip un-needed initialization.<commit_after>/*
 * SchemeShell.cc
 *
 * Simple scheme shell
 * Copyright (c) 2008 Linas Vepstas <linas@linas.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 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, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifdef HAVE_GUILE

#include <opencog/util/Config.h>
#include <opencog/util/Logger.h>
#include <opencog/guile/SchemeEval.h>
#include <opencog/cogserver/server/ConsoleSocket.h>
#include <opencog/cogserver/server/CogServer.h>

#include "SchemeShell.h"

using namespace opencog;

SchemeShell::SchemeShell(void)
{
	normal_prompt = "guile> ";
	if (config().get_bool("ANSI_ENABLED"))
		normal_prompt = config()["ANSI_SCM_PROMPT"];
	else
		normal_prompt = config()["SCM_PROMPT"];

	abort_prompt += normal_prompt;

	pending_prompt = "... ";

	evaluator = SchemeEval::get_evaluator();

	// Set the inital atomspace for this thread.
	SchemeEval::set_scheme_as(&cogserver().getAtomSpace());
}

SchemeShell::~SchemeShell()
{
}

/**
 * Register this shell with the console.
 */
void SchemeShell::thread_init(void)
{
	SchemeEval::set_scheme_as(&cogserver().getAtomSpace());
}

#endif
/* ===================== END OF FILE ============================ */
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: iderdll2.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 20:04:10 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _IDERDLL2_HXX
#define _IDERDLL2_HXX

class StarBASIC;
class SvxSearchItem;
class Accelerator;

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif

#ifndef _GEN_HXX //autogen
#include <tools/gen.hxx>
#endif

#ifndef _LINK_HXX //autogen
#include <tools/link.hxx>
#endif

#include <bastypes.hxx>
#include <bastype2.hxx>

#define INVPOSITION 0x7fff

class BasicIDEData
{
private:
    Accelerator*    pAccelerator;
    SvxSearchItem*  pSearchItem;

    LibInfos        aLibInfos;

    BasicEntryDescriptor    m_aLastEntryDesc;

    Point           aObjCatPos;
    Size            aObjCatSize;

    String          aAddLibPath;
    String          aAddLibFilter;

    USHORT          nBasicDialogCount;

    BOOL            OLD_bRelMacroRecording;
    BOOL            bChoosingMacro;
    BOOL            bShellInCriticalSection;

    void            InitAccelerator();

protected:
    DECL_LINK( GlobalBasicBreakHdl, StarBASIC * );

public:
                            BasicIDEData();
                            ~BasicIDEData();

    LibInfos&               GetLibInfos() { return aLibInfos; }

    BasicEntryDescriptor&   GetLastEntryDescriptor()    { return m_aLastEntryDesc; }
    void                    SetLastEntryDescriptor( BasicEntryDescriptor& rDesc ) { m_aLastEntryDesc = rDesc; }

    BOOL&                   ChoosingMacro()             { return bChoosingMacro; }
    BOOL&                   ShellInCriticalSection()    { return bShellInCriticalSection; }

    USHORT                  GetBasicDialogCount() const { return nBasicDialogCount; }
    void                    IncBasicDialogCount()       { nBasicDialogCount++; }
    void                    DecBasicDialogCount()       { nBasicDialogCount--; }

    SvxSearchItem&          GetSearchItem() const;
    void                    SetSearchItem( const SvxSearchItem& rItem );

    void                    SetObjectCatalogPos( const Point& rPnt )
                                { aObjCatPos = rPnt; }
    const Point&            GetObjectCatalogPos() const
                                { return aObjCatPos; }

    void                    SetObjectCatalogSize( const Size& rSize )
                                { aObjCatSize = rSize; }
    const Size&             GetObjectCatalogSize() const
                                { return aObjCatSize; }

    const String&           GetAddLibPath() const   { return aAddLibPath; }
    void                    SetAddLibPath( const String& rPath ) { aAddLibPath = rPath; }

    const String&           GetAddLibFilter() const { return aAddLibFilter; }
    void                    SetAddLibFilter( const String& rFilter )  { aAddLibFilter = rFilter; }

    Accelerator*            GetAccelerator()
                            {
                                if ( !pAccelerator )
                                    InitAccelerator();
                                return pAccelerator;
                            }

    DECL_LINK( ExecuteMacroEvent, void * );
};

#endif //_IDERDLL2_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.4.244); FILE MERGED 2008/04/01 15:00:37 thb 1.4.244.2: #i85898# Stripping all external header guards 2008/03/28 16:04:45 rt 1.4.244.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: iderdll2.hxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _IDERDLL2_HXX
#define _IDERDLL2_HXX

class StarBASIC;
class SvxSearchItem;
class Accelerator;

#include <tools/string.hxx>
#include <tools/gen.hxx>
#include <tools/link.hxx>

#include <bastypes.hxx>
#include <bastype2.hxx>

#define INVPOSITION 0x7fff

class BasicIDEData
{
private:
    Accelerator*    pAccelerator;
    SvxSearchItem*  pSearchItem;

    LibInfos        aLibInfos;

    BasicEntryDescriptor    m_aLastEntryDesc;

    Point           aObjCatPos;
    Size            aObjCatSize;

    String          aAddLibPath;
    String          aAddLibFilter;

    USHORT          nBasicDialogCount;

    BOOL            OLD_bRelMacroRecording;
    BOOL            bChoosingMacro;
    BOOL            bShellInCriticalSection;

    void            InitAccelerator();

protected:
    DECL_LINK( GlobalBasicBreakHdl, StarBASIC * );

public:
                            BasicIDEData();
                            ~BasicIDEData();

    LibInfos&               GetLibInfos() { return aLibInfos; }

    BasicEntryDescriptor&   GetLastEntryDescriptor()    { return m_aLastEntryDesc; }
    void                    SetLastEntryDescriptor( BasicEntryDescriptor& rDesc ) { m_aLastEntryDesc = rDesc; }

    BOOL&                   ChoosingMacro()             { return bChoosingMacro; }
    BOOL&                   ShellInCriticalSection()    { return bShellInCriticalSection; }

    USHORT                  GetBasicDialogCount() const { return nBasicDialogCount; }
    void                    IncBasicDialogCount()       { nBasicDialogCount++; }
    void                    DecBasicDialogCount()       { nBasicDialogCount--; }

    SvxSearchItem&          GetSearchItem() const;
    void                    SetSearchItem( const SvxSearchItem& rItem );

    void                    SetObjectCatalogPos( const Point& rPnt )
                                { aObjCatPos = rPnt; }
    const Point&            GetObjectCatalogPos() const
                                { return aObjCatPos; }

    void                    SetObjectCatalogSize( const Size& rSize )
                                { aObjCatSize = rSize; }
    const Size&             GetObjectCatalogSize() const
                                { return aObjCatSize; }

    const String&           GetAddLibPath() const   { return aAddLibPath; }
    void                    SetAddLibPath( const String& rPath ) { aAddLibPath = rPath; }

    const String&           GetAddLibFilter() const { return aAddLibFilter; }
    void                    SetAddLibFilter( const String& rFilter )  { aAddLibFilter = rFilter; }

    Accelerator*            GetAccelerator()
                            {
                                if ( !pAccelerator )
                                    InitAccelerator();
                                return pAccelerator;
                            }

    DECL_LINK( ExecuteMacroEvent, void * );
};

#endif //_IDERDLL2_HXX
<|endoftext|>


<commit_before>#ifndef TATUM_COMMON_ANALYSIS_VISITOR_HPP
#define TATUM_COMMON_ANALYSIS_VISITOR_HPP
#include "tatum_error.hpp"
#include "TimingGraph.hpp"
#include "TimingConstraints.hpp"
#include "TimingTags.hpp"

namespace tatum { namespace detail {

/** \file
 *
 * Common analysis functionality for both setup and hold analysis.
 */

/** \class CommonAnalysisVisitor
 *
 * A class satisfying the GraphVisitor concept, which contains common
 * node and edge processing code used by both setup and hold analysis.
 *
 * \see GraphVisitor
 *
 * \tparam AnalysisOps a class defining the setup/hold specific operations
 * \see SetupAnalysisOps
 * \see HoldAnalysisOps
 */
template<class AnalysisOps>
class CommonAnalysisVisitor {
    public:
        CommonAnalysisVisitor(size_t num_tags)
            : ops_(num_tags) { }

        void do_arrival_pre_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const NodeId node_id);
        void do_required_pre_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const NodeId node_id);

        template<class DelayCalc>
        void do_arrival_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, const NodeId node_id);

        template<class DelayCalc>
        void do_required_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, const NodeId node_id);

        void reset() { ops_.reset(); }

    protected:
        AnalysisOps ops_;

    private:
        template<class DelayCalc>
        void do_arrival_traverse_edge(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, const NodeId node_id, const EdgeId edge_id);

        template<class DelayCalc>
        void do_required_traverse_edge(const TimingGraph& tg, const DelayCalc& dc, const NodeId node_id, const EdgeId edge_id);

        bool should_propagate_clock_arr(const TimingGraph& tg, const TimingConstraints& tc, const EdgeId edge_id) const;
        bool is_clock_data_edge(const TimingGraph& tg, const EdgeId edge_id) const;

};

/*
 * Pre-traversal
 */

template<class AnalysisOps>
void CommonAnalysisVisitor<AnalysisOps>::do_arrival_pre_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const NodeId node_id) {
    //Logical Input
    TATUM_ASSERT_MSG(tg.node_in_edges(node_id).size() == 0, "Logical input has input edges: timing graph not levelized.");

    NodeType node_type = tg.node_type(node_id);

    //We don't propagate any tags from constant generators,
    //since they do not effect the dynamic timing behaviour of the
    //system
    if(tc.node_is_constant_generator(node_id)) return;

    if(tc.node_is_clock_source(node_id)) {
        //Generate the appropriate clock tag

        TATUM_ASSERT_MSG(ops_.get_clock_tags(node_id).num_tags() == 0, "Clock source already has clock tags");

        //Find it's domain
        DomainId domain_id = tc.node_clock_domain(node_id);
        TATUM_ASSERT(domain_id);

        //Initialize a clock tag with zero arrival, invalid required time
        //
        //Note: we assume that edge counting has set the effective period constraint assuming a
        //launch edge at time zero.  This means we don't need to do anything special for clocks
        //with rising edges after time zero.
        TimingTag clock_tag = TimingTag(Time(0.), Time(NAN), domain_id, node_id);

        //Add the tag
        ops_.get_clock_tags(node_id).add_tag(clock_tag);

    } else {
        TATUM_ASSERT(node_type == NodeType::SOURCE);

        //A standard primary input, generate the appropriate data tag

        //We assume input delays are on the arc from INPAD_SOURCE to INPAD_OPIN,
        //so we do not need to account for it directly in the arrival time of INPAD_SOURCES

        TATUM_ASSERT_MSG(ops_.get_data_tags(node_id).num_tags() == 0, "Primary input already has data tags");

        DomainId domain_id = tc.node_clock_domain(node_id);
        TATUM_ASSERT(domain_id);

        float input_constraint = tc.input_constraint(node_id, domain_id);
        TATUM_ASSERT(!isnan(input_constraint));

        //Initialize a data tag based on input delay constraint, invalid required time
        TimingTag input_tag = TimingTag(Time(input_constraint), Time(NAN), domain_id, node_id);

        ops_.get_data_tags(node_id).add_tag(input_tag);
    }
}

template<class AnalysisOps>
void CommonAnalysisVisitor<AnalysisOps>::do_required_pre_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const NodeId node_id) {

    TimingTags& node_data_tags = ops_.get_data_tags(node_id);
    TimingTags& node_clock_tags = ops_.get_clock_tags(node_id);

    /*
     * Calculate required times
     */
    TATUM_ASSERT(tg.node_type(node_id) == NodeType::SINK);

    //Sinks corresponding to FF sinks will have propagated (capturing) clock tags,
    //while those corresponding to outpads will not. We initialize the outpad
    //capturing clock tags based on the constraints
    if(node_clock_tags.empty()) {
        //Initialize the clock tags based on the constraints.

        auto output_constraints = tc.output_constraints(node_id);

        if(output_constraints.empty()) {
            //throw tatum::Error("Output unconstrained");
            std::cerr << "Warning: Timing graph " << node_id << " " << tg.node_type(node_id);
            std::cerr << " has no incomming clock tags, and no output constraint. No required time will be calculated\n";
        } else {
            DomainId domain_id = tc.node_clock_domain(node_id);
            TATUM_ASSERT(domain_id);

            float output_constraint = tc.output_constraint(node_id, domain_id);
            TATUM_ASSERT(!isnan(output_constraint));

            for(auto constraint : output_constraints) {
                //TODO: use real constraint value when output delay no-longer on edges
                TimingTag constraint_tag = TimingTag(Time(output_constraint), Time(NAN), constraint.second.domain, node_id);
                node_clock_tags.add_tag(constraint_tag);
            }
        }
    }

    //At this the sink will have a capturing clock tag defined

    //Determine the required time at this sink
    //
    //We need to generate a required time for each clock domain for which there is a data
    //arrival time at this node, while considering all possible clocks that could drive
    //this node (i.e. take the most restrictive constraint accross all clock tags at this
    //node)
    for(TimingTag& node_data_tag : node_data_tags) {
        for(const TimingTag& node_clock_tag : node_clock_tags) {

            //Should we be analyzing paths between these two domains?
            if(tc.should_analyze(node_data_tag.clock_domain(), node_clock_tag.clock_domain())) {

                //We only set a required time if the source domain actually reaches this sink
                //domain.  This is indicated by having a valid arrival time.
                if(node_data_tag.arr_time().valid()) {
                    float clock_constraint = ops_.clock_constraint(tc, node_data_tag.clock_domain(),
                                                                  node_clock_tag.clock_domain());

                    //Update the required time. This will keep the most restrictive constraint.
                    ops_.merge_req_tag(node_data_tag, node_clock_tag.arr_time() + Time(clock_constraint), node_data_tag);
                }
            }
        }
    }
}

/*
 * Arrival Time Operations
 */

template<class AnalysisOps>
template<class DelayCalc>
void CommonAnalysisVisitor<AnalysisOps>::do_arrival_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, NodeId node_id) {
    //Do not propagate arrival tags through constant generators
    if(tc.node_is_constant_generator(node_id)) return;

    //Pull from upstream sources to current node
    for(EdgeId edge_id : tg.node_in_edges(node_id)) {
        do_arrival_traverse_edge(tg, tc, dc, node_id, edge_id);
    }
}

template<class AnalysisOps>
template<class DelayCalc>
void CommonAnalysisVisitor<AnalysisOps>::do_arrival_traverse_edge(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, const NodeId node_id, const EdgeId edge_id) {
    //We must use the tags by reference so we don't accidentally wipe-out any
    //existing tags
    TimingTags& node_data_tags = ops_.get_data_tags(node_id);
    TimingTags& node_clock_tags = ops_.get_clock_tags(node_id);

    //Pulling values from upstream source node
    NodeId src_node_id = tg.edge_src_node(edge_id);

    const Time& edge_delay = ops_.edge_delay(dc, tg, edge_id);
    TATUM_ASSERT(edge_delay.valid());

    const TimingTags& src_clk_tags = ops_.get_clock_tags(src_node_id);
    const TimingTags& src_data_tags = ops_.get_data_tags(src_node_id);

    /*
     * Clock tags
     */

    if(should_propagate_clock_arr(tg, tc, edge_id)) {
        //Propagate the clock tags through the clock network

        for(const TimingTag& src_clk_tag : src_clk_tags) {
            //Standard propagation through the clock network
            ops_.merge_arr_tags(node_clock_tags, src_clk_tag.arr_time() + edge_delay, src_clk_tag);

            if(is_clock_data_edge(tg, edge_id)) {
                //We convert the clock arrival time to a data
                //arrival time at this node (since the clock's
                //arrival launches the data).
                TATUM_ASSERT(tg.node_type(node_id) == NodeType::SOURCE);

                //Make a copy of the tag
                TimingTag launch_tag = src_clk_tag;

                //Update the launch node, since the data is
                //launching from this node
                launch_tag.set_launch_node(node_id);

                //Mark propagated launch time as a DATA tag
                ops_.merge_arr_tags(node_data_tags, launch_tag.arr_time() + edge_delay, launch_tag);
            }
        }
    }

    /*
     * Data tags
     */

    for(const TimingTag& src_data_tag : src_data_tags) {
        //Standard data-path propagation
        ops_.merge_arr_tags(node_data_tags, src_data_tag.arr_time() + edge_delay, src_data_tag);
    }
}

/*
 * Required Time Operations
 */

template<class AnalysisOps>
template<class DelayCalc>
void CommonAnalysisVisitor<AnalysisOps>::do_required_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, const NodeId node_id) {
    //Do not propagate required tags through constant generators
    if(tc.node_is_constant_generator(node_id)) return;

    //Pull from downstream sinks to current node
    for(EdgeId edge_id : tg.node_out_edges(node_id)) {
        do_required_traverse_edge(tg, dc, node_id, edge_id);
    }
}

template<class AnalysisOps>
template<class DelayCalc>
void CommonAnalysisVisitor<AnalysisOps>::do_required_traverse_edge(const TimingGraph& tg, const DelayCalc& dc, const NodeId node_id, const EdgeId edge_id) {
    //We must use the tags by reference so we don't accidentally wipe-out any
    //existing tags
    TimingTags& node_data_tags = ops_.get_data_tags(node_id);

    //Pulling values from downstream sink node
    NodeId sink_node_id = tg.edge_sink_node(edge_id);

    const Time& edge_delay = ops_.edge_delay(dc, tg, edge_id);
    TATUM_ASSERT(edge_delay.valid());

    const TimingTags& sink_data_tags = ops_.get_data_tags(sink_node_id);

    for(const TimingTag& sink_tag : sink_data_tags) {
        //We only propogate the required time if we have a valid arrival time
        auto matched_tag_iter = node_data_tags.find_tag_by_clock_domain(sink_tag.clock_domain());
        if(matched_tag_iter != node_data_tags.end() && matched_tag_iter->arr_time().valid()) {
            //Valid arrival, update required
            ops_.merge_req_tag(*matched_tag_iter, sink_tag.req_time() - edge_delay, sink_tag);
        }
    }
}

template<class AnalysisOps>
bool CommonAnalysisVisitor<AnalysisOps>::should_propagate_clock_arr(const TimingGraph& tg, const TimingConstraints& tc, const EdgeId edge_id) const {
    NodeId src_node_id = tg.edge_src_node(edge_id);

    //We want to propagate clock tags through the arbitrary nodes making up the clock network until
    //we hit another source node (i.e. a FF's output source).
    //
    //To allow tags to propagte from the original source (i.e. the input clock pin) we also allow
    //propagation from defined clock sources
    NodeType src_node_type = tg.node_type(src_node_id);
    if (src_node_type != NodeType::SOURCE) {
        //Not a source, allow propagation
        return true;
    } else if (tc.node_is_clock_source(src_node_id)) {
        //Base-case: the source is a clock source
        TATUM_ASSERT_MSG(src_node_type == NodeType::SOURCE, "Only SOURCEs can be clock sources");
        TATUM_ASSERT_MSG(tg.node_in_edges(src_node_id).empty(), "Clock sources should have no incoming edges");
        return true;
    }
    return false;
}

template<class AnalysisOps>
bool CommonAnalysisVisitor<AnalysisOps>::is_clock_data_edge(const TimingGraph& tg, const EdgeId edge_id) const {
    NodeId edge_src_node = tg.edge_src_node(edge_id);
    NodeId edge_sink_node = tg.edge_sink_node(edge_id);

    return (tg.node_type(edge_src_node) == NodeType::CPIN) && (tg.node_type(edge_sink_node) == NodeType::SOURCE);
}

}} //namepsace

#endif
<commit_msg>Improve function names and some code organization<commit_after>#ifndef TATUM_COMMON_ANALYSIS_VISITOR_HPP
#define TATUM_COMMON_ANALYSIS_VISITOR_HPP
#include "tatum_error.hpp"
#include "TimingGraph.hpp"
#include "TimingConstraints.hpp"
#include "TimingTags.hpp"

namespace tatum { namespace detail {

/** \file
 *
 * Common analysis functionality for both setup and hold analysis.
 */

/** \class CommonAnalysisVisitor
 *
 * A class satisfying the GraphVisitor concept, which contains common
 * node and edge processing code used by both setup and hold analysis.
 *
 * \see GraphVisitor
 *
 * \tparam AnalysisOps a class defining the setup/hold specific operations
 * \see SetupAnalysisOps
 * \see HoldAnalysisOps
 */
template<class AnalysisOps>
class CommonAnalysisVisitor {
    public:
        CommonAnalysisVisitor(size_t num_tags)
            : ops_(num_tags) { }

        void do_arrival_pre_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const NodeId node_id);
        void do_required_pre_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const NodeId node_id);

        template<class DelayCalc>
        void do_arrival_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, const NodeId node_id);

        template<class DelayCalc>
        void do_required_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, const NodeId node_id);

        void reset() { ops_.reset(); }

    protected:
        AnalysisOps ops_;

    private:
        template<class DelayCalc>
        void do_arrival_traverse_edge(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, const NodeId node_id, const EdgeId edge_id);

        template<class DelayCalc>
        void do_required_traverse_edge(const TimingGraph& tg, const DelayCalc& dc, const NodeId node_id, const EdgeId edge_id);

        bool should_propagate_clock_arr(const TimingGraph& tg, const TimingConstraints& tc, const EdgeId edge_id) const;
        bool is_clock_data_launch_edge(const TimingGraph& tg, const EdgeId edge_id) const;
        bool is_clock_data_capture_edge(const TimingGraph& tg, const EdgeId edge_id) const;

};

/*
 * Pre-traversal
 */

template<class AnalysisOps>
void CommonAnalysisVisitor<AnalysisOps>::do_arrival_pre_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const NodeId node_id) {
    //Logical Input
    TATUM_ASSERT_MSG(tg.node_in_edges(node_id).size() == 0, "Logical input has input edges: timing graph not levelized.");

    NodeType node_type = tg.node_type(node_id);

    if(tc.node_is_constant_generator(node_id)) {
        //We don't propagate any tags from constant generators,
        //since they do not effect the dynamic timing behaviour of the
        //system
        return;
    }

    TATUM_ASSERT(node_type == NodeType::SOURCE);

    if(tc.node_is_clock_source(node_id)) {
        //Generate the appropriate clock tag

        TATUM_ASSERT_MSG(ops_.get_clock_tags(node_id).num_tags() == 0, "Clock source already has clock tags");

        //Find it's domain
        DomainId domain_id = tc.node_clock_domain(node_id);
        TATUM_ASSERT(domain_id);

        //Initialize a clock tag with zero arrival, invalid required time
        //
        //Note: we assume that edge counting has set the effective period constraint assuming a
        //launch edge at time zero.  This means we don't need to do anything special for clocks
        //with rising edges after time zero.
        TimingTag clock_tag = TimingTag(Time(0.), Time(NAN), domain_id, node_id);

        //Add the tag
        ops_.get_clock_tags(node_id).add_tag(clock_tag);

    } else {

        //A standard primary input, generate the appropriate data tag

        TATUM_ASSERT_MSG(ops_.get_data_tags(node_id).num_tags() == 0, "Primary input already has data tags");

        DomainId domain_id = tc.node_clock_domain(node_id);
        TATUM_ASSERT(domain_id);

        float input_constraint = tc.input_constraint(node_id, domain_id);
        TATUM_ASSERT(!isnan(input_constraint));

        //Initialize a data tag based on input delay constraint, invalid required time
        TimingTag input_tag = TimingTag(Time(input_constraint), Time(NAN), domain_id, node_id);

        ops_.get_data_tags(node_id).add_tag(input_tag);
    }
}

template<class AnalysisOps>
void CommonAnalysisVisitor<AnalysisOps>::do_required_pre_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const NodeId node_id) {

    TimingTags& node_data_tags = ops_.get_data_tags(node_id);
    TimingTags& node_clock_tags = ops_.get_clock_tags(node_id);

    /*
     * Calculate required times
     */

    TATUM_ASSERT(tg.node_type(node_id) == NodeType::SINK);

    //Sinks corresponding to FF sinks will have propagated (capturing) clock tags,
    //while those corresponding to outpads will not. To treat them uniformly, we
    //initialize outpads with capturing clock tags based on the ouput constraints.
    if(node_clock_tags.empty()) {
        //Initialize the clock tags based on the constraints.

        auto output_constraints = tc.output_constraints(node_id);

        if(output_constraints.empty()) {
            //throw tatum::Error("Output unconstrained");
            std::cerr << "Warning: Timing graph " << node_id << " " << tg.node_type(node_id);
            std::cerr << " has no incomming clock tags, and no output constraint. No required time will be calculated\n";
        } else {
            DomainId domain_id = tc.node_clock_domain(node_id);
            TATUM_ASSERT(domain_id);

            float output_constraint = tc.output_constraint(node_id, domain_id);
            TATUM_ASSERT(!isnan(output_constraint));

            for(auto constraint : output_constraints) {
                TimingTag constraint_tag = TimingTag(Time(output_constraint), Time(NAN), constraint.second.domain, node_id);
                node_clock_tags.add_tag(constraint_tag);
            }
        }
    }

    //At this point the sink will have a capturing clock tag defined

    //Determine the required time at this sink
    //
    //We need to generate a required time for each clock domain for which there is a data
    //arrival time at this node, while considering all possible clocks that could drive
    //this node (i.e. take the most restrictive constraint accross all clock tags at this
    //node)
    for(TimingTag& node_data_tag : node_data_tags) {
        for(const TimingTag& node_clock_tag : node_clock_tags) {

            //Should we be analyzing paths between these two domains?
            if(tc.should_analyze(node_data_tag.clock_domain(), node_clock_tag.clock_domain())) {

                //We only set a required time if the source domain actually reaches this sink
                //domain.  This is indicated by having a valid arrival time.
                if(node_data_tag.arr_time().valid()) {
                    float clock_constraint = ops_.clock_constraint(tc, node_data_tag.clock_domain(),
                                                                  node_clock_tag.clock_domain());

                    //Update the required time. This will keep the most restrictive constraint.
                    ops_.merge_req_tag(node_data_tag, node_clock_tag.arr_time() + Time(clock_constraint), node_data_tag);
                }
            }
        }
    }
}

/*
 * Arrival Time Operations
 */

template<class AnalysisOps>
template<class DelayCalc>
void CommonAnalysisVisitor<AnalysisOps>::do_arrival_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, NodeId node_id) {
    //Do not propagate arrival tags through constant generators
    if(tc.node_is_constant_generator(node_id)) return;

    //Pull from upstream sources to current node
    for(EdgeId edge_id : tg.node_in_edges(node_id)) {
        do_arrival_traverse_edge(tg, tc, dc, node_id, edge_id);
    }
}

template<class AnalysisOps>
template<class DelayCalc>
void CommonAnalysisVisitor<AnalysisOps>::do_arrival_traverse_edge(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, const NodeId node_id, const EdgeId edge_id) {
    //We must use the tags by reference so we don't accidentally wipe-out any
    //existing tags
    TimingTags& node_data_tags = ops_.get_data_tags(node_id);
    TimingTags& node_clock_tags = ops_.get_clock_tags(node_id);

    //Pulling values from upstream source node
    NodeId src_node_id = tg.edge_src_node(edge_id);

    const Time& edge_delay = ops_.edge_delay(dc, tg, edge_id);
    TATUM_ASSERT(edge_delay.valid());

    const TimingTags& src_clk_tags = ops_.get_clock_tags(src_node_id);
    const TimingTags& src_data_tags = ops_.get_data_tags(src_node_id);

    /*
     * Clock tags
     */

    if(should_propagate_clock_arr(tg, tc, edge_id)) {
        //Propagate the clock tags through the clock network

        for(const TimingTag& src_clk_tag : src_clk_tags) {
            //Standard propagation through the clock network
            ops_.merge_arr_tags(node_clock_tags, src_clk_tag.arr_time() + edge_delay, src_clk_tag);

            if(is_clock_data_launch_edge(tg, edge_id)) {
                //We convert the clock arrival time to a data
                //arrival time at this node (since the clock's
                //arrival launches the data).
                TATUM_ASSERT(tg.node_type(node_id) == NodeType::SOURCE);

                //Make a copy of the tag
                TimingTag launch_tag = src_clk_tag;

                //Update the launch node, since the data is
                //launching from this node
                launch_tag.set_launch_node(node_id);

                //Mark propagated launch time as a DATA tag
                ops_.merge_arr_tags(node_data_tags, launch_tag.arr_time() + edge_delay, launch_tag);
            }
        }
    }

    /*
     * Data tags
     */

    for(const TimingTag& src_data_tag : src_data_tags) {
        //Standard data-path propagation
        ops_.merge_arr_tags(node_data_tags, src_data_tag.arr_time() + edge_delay, src_data_tag);
    }
}

/*
 * Required Time Operations
 */

template<class AnalysisOps>
template<class DelayCalc>
void CommonAnalysisVisitor<AnalysisOps>::do_required_traverse_node(const TimingGraph& tg, const TimingConstraints& tc, const DelayCalc& dc, const NodeId node_id) {
    //Do not propagate required tags through constant generators
    if(tc.node_is_constant_generator(node_id)) return;

    //Pull from downstream sinks to current node
    for(EdgeId edge_id : tg.node_out_edges(node_id)) {
        do_required_traverse_edge(tg, dc, node_id, edge_id);
    }
}

template<class AnalysisOps>
template<class DelayCalc>
void CommonAnalysisVisitor<AnalysisOps>::do_required_traverse_edge(const TimingGraph& tg, const DelayCalc& dc, const NodeId node_id, const EdgeId edge_id) {
    //We must use the tags by reference so we don't accidentally wipe-out any
    //existing tags
    TimingTags& node_data_tags = ops_.get_data_tags(node_id);

    //Pulling values from downstream sink node
    NodeId sink_node_id = tg.edge_sink_node(edge_id);

    const Time& edge_delay = ops_.edge_delay(dc, tg, edge_id);
    TATUM_ASSERT(edge_delay.valid());

    const TimingTags& sink_data_tags = ops_.get_data_tags(sink_node_id);

    for(const TimingTag& sink_tag : sink_data_tags) {
        //We only propogate the required time if we have a valid arrival time
        auto matched_tag_iter = node_data_tags.find_tag_by_clock_domain(sink_tag.clock_domain());
        if(matched_tag_iter != node_data_tags.end() && matched_tag_iter->arr_time().valid()) {
            //Valid arrival, update required
            ops_.merge_req_tag(*matched_tag_iter, sink_tag.req_time() - edge_delay, sink_tag);
        }
    }
}

template<class AnalysisOps>
bool CommonAnalysisVisitor<AnalysisOps>::should_propagate_clock_arr(const TimingGraph& tg, const TimingConstraints& tc, const EdgeId edge_id) const {
    //We want to propagate clock tags through the arbitrary nodes making up the clock network until
    //we hit another source node (i.e. a FF's output source).
    //
    //To allow tags to propagte from the original source (i.e. the input clock pin) we also allow
    //propagation from defined clock sources
    NodeId src_node_id = tg.edge_src_node(edge_id);
    NodeType src_node_type = tg.node_type(src_node_id);
    if (src_node_type != NodeType::SOURCE) {
        //Not a source, allow propagation
        return true;
    } else if (tc.node_is_clock_source(src_node_id)) {
        //Base-case: the source is a clock source
        TATUM_ASSERT_MSG(src_node_type == NodeType::SOURCE, "Only SOURCEs can be clock sources");
        TATUM_ASSERT_MSG(tg.node_in_edges(src_node_id).empty(), "Clock sources should have no incoming edges");
        return true;
    }
    return false;
}

template<class AnalysisOps>
bool CommonAnalysisVisitor<AnalysisOps>::is_clock_data_launch_edge(const TimingGraph& tg, const EdgeId edge_id) const {
    NodeId edge_src_node = tg.edge_src_node(edge_id);
    NodeId edge_sink_node = tg.edge_sink_node(edge_id);

    return (tg.node_type(edge_src_node) == NodeType::CPIN) && (tg.node_type(edge_sink_node) == NodeType::SOURCE);
}

template<class AnalysisOps>
bool CommonAnalysisVisitor<AnalysisOps>::is_clock_data_capture_edge(const TimingGraph& tg, const EdgeId edge_id) const {
    NodeId edge_src_node = tg.edge_src_node(edge_id);
    NodeId edge_sink_node = tg.edge_sink_node(edge_id);

    return (tg.node_type(edge_src_node) == NodeType::CPIN) && (tg.node_type(edge_sink_node) == NodeType::SINK);
}

}} //namepsace

#endif
<|endoftext|>


<commit_before>/* **** **** **** **** **** **** **** **** *
 *
 *         _/        _/        _/
 *        _/_/_/    _/_/_/    _/_/_/
 *       _/    _/  _/    _/  _/    _/
 *      _/    _/  _/    _/  _/    _/
 *     _/_/_/    _/_/_/    _/_/_/
 *
 * bit by bit
 * bbb/core/traits/function_traits.hpp
 *
 * author: ISHII 2bit
 * mail:   bit_by_bit@2bit.jp
 *
 * **** **** **** **** **** **** **** **** */

#pragma once

#include <type_traits>
#include <tuple>
#include <functional>

#include <bbb/core/basic.hpp>
#include <bbb/core/traits/type_traits.hpp>

namespace bbb {
    namespace function_info {
        namespace detail {
            template <typename ret, typename ... arguments>
            struct function_traits {
                static constexpr std::size_t arity = sizeof...(arguments);
                using result_type = ret;
                using arguments_types_tuple = std::tuple<arguments ...>;
                template <std::size_t index>
                using argument_type = type_at<index, arguments ...>;
                using function_type = std::function<ret(arguments ...)>;
                template <typename function_t>
                static constexpr function_type cast(function_t f) {
                    return static_cast<function_type>(f);
                }
            };
        };

        template <typename T>
        struct function_traits : public function_traits<decltype(&T::operator())> {};

        template <typename class_type, typename ret, typename ... arguments>
        struct function_traits<ret(class_type::*)(arguments ...) const>
            : detail::function_traits<ret, arguments ...> {};

        template <typename class_type, typename ret, typename ... arguments>
        struct function_traits<ret(class_type::*)(arguments ...)>
            : detail::function_traits<ret, arguments ...> {};

        template <typename ret, typename ... arguments>
        struct function_traits<ret(*)(arguments ...)>
            : detail::function_traits<ret, arguments ...> {};

        template <typename ret, typename ... arguments>
        struct function_traits<ret(arguments ...)>
            : detail::function_traits<ret, arguments ...> {};

        template <typename ret, typename ... arguments>
        struct function_traits<std::function<ret(arguments ...)>>
            : detail::function_traits<ret, arguments ...> {};

        template<typename T>
        using result_type = typename function_traits<T>::result_type;

        template<typename T>
        using arguments_types_tuple = typename function_traits<T>::arguments_types_tuple;

        template<typename T, std::size_t index>
        using argument_type = typename function_traits<T>::template argument_type<index>;

        template<typename T>
        struct arity {
            static constexpr std::size_t value = function_traits<T>::arity;
        };

        template <typename patient>
        struct has_call_operator {
            template <typename inner_patient, decltype(&inner_patient::operator())> struct checker {};
            template <typename inner_patient> static std::true_type  check(checker<inner_patient, &inner_patient::operator()> *);
            template <typename>               static std::false_type check(...);
            using type = decltype(check<patient>(nullptr));
            static constexpr bool value = type::value;
        };

        template <typename patient>
        constexpr bool is_callable(const patient &) {
            return std::is_function<patient>::value || has_call_operator<patient>::value;
        };
    };
    using namespace function_info;
};
<commit_msg>missed _t<commit_after>/* **** **** **** **** **** **** **** **** *
 *
 *         _/        _/        _/
 *        _/_/_/    _/_/_/    _/_/_/
 *       _/    _/  _/    _/  _/    _/
 *      _/    _/  _/    _/  _/    _/
 *     _/_/_/    _/_/_/    _/_/_/
 *
 * bit by bit
 * bbb/core/traits/function_traits.hpp
 *
 * author: ISHII 2bit
 * mail:   bit_by_bit@2bit.jp
 *
 * **** **** **** **** **** **** **** **** */

#pragma once

#include <type_traits>
#include <tuple>
#include <functional>

#include <bbb/core/basic.hpp>
#include <bbb/core/traits/type_traits.hpp>

namespace bbb {
    namespace function_info {
        namespace detail {
            template <typename ret, typename ... arguments>
            struct function_traits {
                static constexpr std::size_t arity = sizeof...(arguments);
                using result_type = ret;
                using arguments_types_tuple = std::tuple<arguments ...>;
                template <std::size_t index>
                using argument_type = type_at_t<index, arguments ...>;
                using function_type = std::function<ret(arguments ...)>;
                template <typename function_t>
                static constexpr function_type cast(function_t f) {
                    return static_cast<function_type>(f);
                }
            };
        };

        template <typename T>
        struct function_traits : public function_traits<decltype(&T::operator())> {};

        template <typename class_type, typename ret, typename ... arguments>
        struct function_traits<ret(class_type::*)(arguments ...) const>
            : detail::function_traits<ret, arguments ...> {};

        template <typename class_type, typename ret, typename ... arguments>
        struct function_traits<ret(class_type::*)(arguments ...)>
            : detail::function_traits<ret, arguments ...> {};

        template <typename ret, typename ... arguments>
        struct function_traits<ret(*)(arguments ...)>
            : detail::function_traits<ret, arguments ...> {};

        template <typename ret, typename ... arguments>
        struct function_traits<ret(arguments ...)>
            : detail::function_traits<ret, arguments ...> {};

        template <typename ret, typename ... arguments>
        struct function_traits<std::function<ret(arguments ...)>>
            : detail::function_traits<ret, arguments ...> {};

        template<typename T>
        using result_type = typename function_traits<T>::result_type;

        template<typename T>
        using arguments_types_tuple = typename function_traits<T>::arguments_types_tuple;

        template<typename T, std::size_t index>
        using argument_type = typename function_traits<T>::template argument_type<index>;

        template<typename T>
        struct arity {
            static constexpr std::size_t value = function_traits<T>::arity;
        };

        template <typename patient>
        struct has_call_operator {
            template <typename inner_patient, decltype(&inner_patient::operator())> struct checker {};
            template <typename inner_patient> static std::true_type  check(checker<inner_patient, &inner_patient::operator()> *);
            template <typename>               static std::false_type check(...);
            using type = decltype(check<patient>(nullptr));
            static constexpr bool value = type::value;
        };

        template <typename patient>
        constexpr bool is_callable(const patient &) {
            return std::is_function<patient>::value || has_call_operator<patient>::value;
        };
    };
    using namespace function_info;
};
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2022 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwopy/pydatareaders.h>

#include <inviwo/core/io/datareader.h>
#include <inviwo/core/io/datareaderfactory.h>
#include <inviwo/core/datastructures/geometry/mesh.h>
#include <inviwo/core/datastructures/image/image.h>
#include <inviwo/core/datastructures/volume/volume.h>

namespace inviwo {

// Allow overriding virtual functions from Python
template <typename T>
class DataReaderTypeTrampoline : public DataReaderType<T>,
                                 public pybind11::trampoline_self_life_support {
public:
    using DataReaderType<T>::DataReaderType;  // Inherit constructors

    virtual DataReaderType<T>* clone() const override {
        PYBIND11_OVERRIDE_PURE(DataReaderType<T>*, /* Return type */
                               DataReaderType<T>,  /* Parent class */
                               clone, /* Name of function in C++ (must match Python name) */
        );
    }
    virtual bool setOption(std::string_view key, std::any value) override {
        PYBIND11_OVERRIDE(bool,              /* Return type */
                          DataReaderType<T>, /* Parent class */
                          setOption,         /* Name of function in C++ (must match Python name) */
                          key, value         /* Argument(s) */
        );
    }
    virtual std::shared_ptr<T> readData(std::string_view filePath) override {
        PYBIND11_OVERRIDE_PURE(std::shared_ptr<T>, /* Return type */
                               DataReaderType<T>,  /* Parent class */
                               readData, /* Name of function in C++ (must match Python name) */
                               filePath  /* Argument(s) */
        );
    }
    virtual std::shared_ptr<T> readData(std::string_view filePath, MetaDataOwner* owner) override {
        PYBIND11_OVERRIDE(std::shared_ptr<T>, /* Return type */
                          DataReaderType<T>,  /* Parent class */
                          readData,           /* Name of function in C++ (must match Python name) */
                          filePath, owner     /* Argument(s) */
        );
    }
};

template <typename T>
void exposeFactoryReaderType(pybind11::class_<DataReaderFactory>& r, std::string_view type) {
    namespace py = pybind11;
    r.def(fmt::format("getExtensionsFor{}", type).c_str(),
          (std::vector<FileExtension>(DataReaderFactory::*)() const) &
              DataReaderFactory::getExtensionsForType<T>)
        .def(fmt::format("get{}Reader", type).c_str(),
             (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(std::string_view) const) &
                 DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(
            fmt::format("get{}Reader", type).c_str(),
            (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(const FileExtension&) const) &
                DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(fmt::format("get{}Reader", type).c_str(),
             (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(const FileExtension&,
                                                                       std::string_view) const) &
                 DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(fmt::format("has{}Reader", type).c_str(),
             (bool (DataReaderFactory::*)(std::string_view) const) &
                 DataReaderFactory::hasReaderForTypeAndExtension<T>);
}

void exposeDataReaders(pybind11::module& m) {
    namespace py = pybind11;

    // https://pybind11.readthedocs.io/en/stable/advanced/classes.html#binding-classes-with-template-parameters
    py::class_<DataReaderType<Image>, DataReaderTypeTrampoline<Image>>(
        m, "ImageDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Image>::readData))
        .def("readData",
             py::overload_cast<std::string_view, MetaDataOwner*>(&DataReaderType<Image>::readData));
    py::class_<DataReaderType<Mesh>, DataReaderTypeTrampoline<Mesh>>(m,
                                                                                "MeshDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Mesh>::readData))
        .def("readData",
             py::overload_cast<std::string_view, MetaDataOwner*>(&DataReaderType<Mesh>::readData));
    py::class_<DataReaderType<Volume>, DataReaderTypeTrampoline<Volume>>(
        m, "VolumeDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Volume>::readData))
        .def("readData", py::overload_cast<std::string_view, MetaDataOwner*>(
                             &DataReaderType<Volume>::readData));

    auto fr =
        py::class_<DataReaderFactory>(m, "DataReaderFactory")
            .def(py::init<>())
            .def("create",
                 (std::unique_ptr<DataReader>(DataReaderFactory::*)(const FileExtension&) const) &
                     DataReaderFactory::create)
            .def("create",
                 (std::unique_ptr<DataReader>(DataReaderFactory::*)(std::string_view) const) &
                     DataReaderFactory::create)
            .def("hasKey",
                 (bool (DataReaderFactory::*)(std::string_view) const) & DataReaderFactory::hasKey)
            .def("hasKey", (bool (DataReaderFactory::*)(const FileExtension&) const) &
                               DataReaderFactory::hasKey);
    // No good way of dealing with template return types so we manually define one for each known
    // type.
    // https://github.com/pybind/pybind11/issues/1667#issuecomment-454348004
    // If your module exposes a new reader type it will have to bind getXXXReader.
    exposeFactoryReaderType<Image>(fr, "Image");
    exposeFactoryReaderType<Mesh>(fr, "Mesh");
    exposeFactoryReaderType<Volume>(fr, "Volume");
}

}  // namespace inviwo
<commit_msg>Jenkins: Format fixes<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2022 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwopy/pydatareaders.h>

#include <inviwo/core/io/datareader.h>
#include <inviwo/core/io/datareaderfactory.h>
#include <inviwo/core/datastructures/geometry/mesh.h>
#include <inviwo/core/datastructures/image/image.h>
#include <inviwo/core/datastructures/volume/volume.h>

namespace inviwo {

// Allow overriding virtual functions from Python
template <typename T>
class DataReaderTypeTrampoline : public DataReaderType<T>,
                                 public pybind11::trampoline_self_life_support {
public:
    using DataReaderType<T>::DataReaderType;  // Inherit constructors

    virtual DataReaderType<T>* clone() const override {
        PYBIND11_OVERRIDE_PURE(DataReaderType<T>*, /* Return type */
                               DataReaderType<T>,  /* Parent class */
                               clone, /* Name of function in C++ (must match Python name) */
        );
    }
    virtual bool setOption(std::string_view key, std::any value) override {
        PYBIND11_OVERRIDE(bool,              /* Return type */
                          DataReaderType<T>, /* Parent class */
                          setOption,         /* Name of function in C++ (must match Python name) */
                          key, value         /* Argument(s) */
        );
    }
    virtual std::shared_ptr<T> readData(std::string_view filePath) override {
        PYBIND11_OVERRIDE_PURE(std::shared_ptr<T>, /* Return type */
                               DataReaderType<T>,  /* Parent class */
                               readData, /* Name of function in C++ (must match Python name) */
                               filePath  /* Argument(s) */
        );
    }
    virtual std::shared_ptr<T> readData(std::string_view filePath, MetaDataOwner* owner) override {
        PYBIND11_OVERRIDE(std::shared_ptr<T>, /* Return type */
                          DataReaderType<T>,  /* Parent class */
                          readData,           /* Name of function in C++ (must match Python name) */
                          filePath, owner     /* Argument(s) */
        );
    }
};

template <typename T>
void exposeFactoryReaderType(pybind11::class_<DataReaderFactory>& r, std::string_view type) {
    namespace py = pybind11;
    r.def(fmt::format("getExtensionsFor{}", type).c_str(),
          (std::vector<FileExtension>(DataReaderFactory::*)() const) &
              DataReaderFactory::getExtensionsForType<T>)
        .def(fmt::format("get{}Reader", type).c_str(),
             (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(std::string_view) const) &
                 DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(
            fmt::format("get{}Reader", type).c_str(),
            (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(const FileExtension&) const) &
                DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(fmt::format("get{}Reader", type).c_str(),
             (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(const FileExtension&,
                                                                       std::string_view) const) &
                 DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(fmt::format("has{}Reader", type).c_str(),
             (bool (DataReaderFactory::*)(std::string_view) const) &
                 DataReaderFactory::hasReaderForTypeAndExtension<T>);
}

void exposeDataReaders(pybind11::module& m) {
    namespace py = pybind11;

    // https://pybind11.readthedocs.io/en/stable/advanced/classes.html#binding-classes-with-template-parameters
    py::class_<DataReaderType<Image>, DataReaderTypeTrampoline<Image>>(m, "ImageDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Image>::readData))
        .def("readData",
             py::overload_cast<std::string_view, MetaDataOwner*>(&DataReaderType<Image>::readData));
    py::class_<DataReaderType<Mesh>, DataReaderTypeTrampoline<Mesh>>(m, "MeshDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Mesh>::readData))
        .def("readData",
             py::overload_cast<std::string_view, MetaDataOwner*>(&DataReaderType<Mesh>::readData));
    py::class_<DataReaderType<Volume>, DataReaderTypeTrampoline<Volume>>(m, "VolumeDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Volume>::readData))
        .def("readData", py::overload_cast<std::string_view, MetaDataOwner*>(
                             &DataReaderType<Volume>::readData));

    auto fr =
        py::class_<DataReaderFactory>(m, "DataReaderFactory")
            .def(py::init<>())
            .def("create",
                 (std::unique_ptr<DataReader>(DataReaderFactory::*)(const FileExtension&) const) &
                     DataReaderFactory::create)
            .def("create",
                 (std::unique_ptr<DataReader>(DataReaderFactory::*)(std::string_view) const) &
                     DataReaderFactory::create)
            .def("hasKey",
                 (bool (DataReaderFactory::*)(std::string_view) const) & DataReaderFactory::hasKey)
            .def("hasKey", (bool (DataReaderFactory::*)(const FileExtension&) const) &
                               DataReaderFactory::hasKey);
    // No good way of dealing with template return types so we manually define one for each known
    // type.
    // https://github.com/pybind/pybind11/issues/1667#issuecomment-454348004
    // If your module exposes a new reader type it will have to bind getXXXReader.
    exposeFactoryReaderType<Image>(fr, "Image");
    exposeFactoryReaderType<Mesh>(fr, "Mesh");
    exposeFactoryReaderType<Volume>(fr, "Volume");
}

}  // namespace inviwo
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2022 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwopy/pydatareaders.h>

#include <inviwo/core/io/datareader.h>
#include <inviwo/core/io/datareaderfactory.h>
#include <inviwo/core/datastructures/geometry/mesh.h>
#include <inviwo/core/datastructures/image/image.h>
#include <inviwo/core/datastructures/volume/volume.h>

namespace inviwo {

// Allow overriding virtual functions from Python
template <typename T>
class DataReaderTypeTrampoline : public DataReaderType<T>,
                                 public pybind11::trampoline_self_life_support {
public:
    using DataReaderType<T>::DataReaderType;  // Inherit constructors

    virtual DataReaderType<T>* clone() const override {
        PYBIND11_OVERRIDE_PURE(DataReaderType<T>*, /* Return type */
                               DataReaderType<T>,  /* Parent class */
                               clone, /* Name of function in C++ (must match Python name) */
        );
    }
    virtual bool setOption(std::string_view key, std::any value) override {
        PYBIND11_OVERRIDE(bool,              /* Return type */
                          DataReaderType<T>, /* Parent class */
                          setOption,         /* Name of function in C++ (must match Python name) */
                          key, value         /* Argument(s) */
        );
    }
    virtual std::shared_ptr<T> readData(std::string_view filePath) override {
        PYBIND11_OVERRIDE_PURE(std::shared_ptr<T>, /* Return type */
                               DataReaderType<T>,  /* Parent class */
                               readData, /* Name of function in C++ (must match Python name) */
                               filePath  /* Argument(s) */
        );
    }
    virtual std::shared_ptr<T> readData(std::string_view filePath, MetaDataOwner* owner) override {
        PYBIND11_OVERRIDE(std::shared_ptr<T>, /* Return type */
                          DataReaderType<T>,  /* Parent class */
                          readData,           /* Name of function in C++ (must match Python name) */
                          filePath, owner     /* Argument(s) */
        );
    }
};

template <typename T>
void exposeFactoryReaderType(pybind11::class_<DataReaderFactory>& r, std::string_view type) {
    namespace py = pybind11;
    r.def(fmt::format("getExtensionsFor{}", type).c_str(),
          (std::vector<FileExtension>(DataReaderFactory::*)() const) &
              DataReaderFactory::getExtensionsForType<T>)
        .def(fmt::format("get{}Reader", type).c_str(),
             (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(std::string_view) const) &
                 DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(
            fmt::format("get{}Reader", type).c_str(),
            (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(const FileExtension&) const) &
                DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(fmt::format("get{}Reader", type).c_str(),
             (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(const FileExtension&,
                                                                       std::string_view) const) &
                 DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(fmt::format("has{}Reader", type).c_str(),
             (bool (DataReaderFactory::*)(std::string_view) const) &
                 DataReaderFactory::hasReaderForTypeAndExtension<T>);
}

void exposeDataReaders(pybind11::module& m) {
    namespace py = pybind11;

    // https://pybind11.readthedocs.io/en/stable/advanced/classes.html#binding-classes-with-template-parameters
    py::class_<DataReaderType<Image>, DataReaderTypeTrampoline<Image>>(m, "ImageDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Image>::readData))
        .def("readData",
             py::overload_cast<std::string_view, MetaDataOwner*>(&DataReaderType<Image>::readData));
    py::class_<DataReaderType<Mesh>, DataReaderTypeTrampoline<Mesh>>(m, "MeshDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Mesh>::readData))
        .def("readData",
             py::overload_cast<std::string_view, MetaDataOwner*>(&DataReaderType<Mesh>::readData));
    py::class_<DataReaderType<Volume>, DataReaderTypeTrampoline<Volume>>(m, "VolumeDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Volume>::readData))
        .def("readData", py::overload_cast<std::string_view, MetaDataOwner*>(
                             &DataReaderType<Volume>::readData));

    auto fr =
        py::class_<DataReaderFactory>(m, "DataReaderFactory")
            .def(py::init<>())
            .def("create",
                 (std::unique_ptr<DataReader>(DataReaderFactory::*)(const FileExtension&) const) &
                     DataReaderFactory::create)
            .def("create",
                 (std::unique_ptr<DataReader>(DataReaderFactory::*)(std::string_view) const) &
                     DataReaderFactory::create)
            .def("hasKey",
                 (bool (DataReaderFactory::*)(std::string_view) const) & DataReaderFactory::hasKey)
            .def("hasKey", (bool (DataReaderFactory::*)(const FileExtension&) const) &
                               DataReaderFactory::hasKey);
    // No good way of dealing with template return types so we manually define one for each known
    // type.
    // https://github.com/pybind/pybind11/issues/1667#issuecomment-454348004
    // If your module exposes a new reader type it will have to bind getXXXReader.
    exposeFactoryReaderType<Image>(fr, "Image");
    exposeFactoryReaderType<Mesh>(fr, "Mesh");
    exposeFactoryReaderType<Volume>(fr, "Volume");
}

}  // namespace inviwo
<commit_msg>Python3: Expose DataReader class.<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2022 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwopy/pydatareaders.h>

#include <inviwo/core/io/datareader.h>
#include <inviwo/core/io/datareaderfactory.h>
#include <inviwo/core/datastructures/geometry/mesh.h>
#include <inviwo/core/datastructures/image/image.h>
#include <inviwo/core/datastructures/volume/volume.h>

namespace inviwo {

// Allow overriding virtual functions from Python
template <typename T>
class DataReaderTypeTrampoline : public DataReaderType<T>,
                                 public pybind11::trampoline_self_life_support {
public:
    using DataReaderType<T>::DataReaderType;  // Inherit constructors

    virtual DataReaderType<T>* clone() const override {
        PYBIND11_OVERRIDE_PURE(DataReaderType<T>*, /* Return type */
                               DataReaderType<T>,  /* Parent class */
                               clone, /* Name of function in C++ (must match Python name) */
        );
    }
    virtual bool setOption(std::string_view key, std::any value) override {
        PYBIND11_OVERRIDE(bool,              /* Return type */
                          DataReaderType<T>, /* Parent class */
                          setOption,         /* Name of function in C++ (must match Python name) */
                          key, value         /* Argument(s) */
        );
    }
    virtual std::shared_ptr<T> readData(std::string_view filePath) override {
        PYBIND11_OVERRIDE_PURE(std::shared_ptr<T>, /* Return type */
                               DataReaderType<T>,  /* Parent class */
                               readData, /* Name of function in C++ (must match Python name) */
                               filePath  /* Argument(s) */
        );
    }
    virtual std::shared_ptr<T> readData(std::string_view filePath, MetaDataOwner* owner) override {
        PYBIND11_OVERRIDE(std::shared_ptr<T>, /* Return type */
                          DataReaderType<T>,  /* Parent class */
                          readData,           /* Name of function in C++ (must match Python name) */
                          filePath, owner     /* Argument(s) */
        );
    }
};

template <typename T>
void exposeFactoryReaderType(pybind11::class_<DataReaderFactory>& r, std::string_view type) {
    namespace py = pybind11;
    r.def(fmt::format("getExtensionsFor{}", type).c_str(),
          (std::vector<FileExtension>(DataReaderFactory::*)() const) &
              DataReaderFactory::getExtensionsForType<T>)
        .def(fmt::format("get{}Reader", type).c_str(),
             (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(std::string_view) const) &
                 DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(
            fmt::format("get{}Reader", type).c_str(),
            (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(const FileExtension&) const) &
                DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(fmt::format("get{}Reader", type).c_str(),
             (std::unique_ptr<DataReaderType<T>>(DataReaderFactory::*)(const FileExtension&,
                                                                       std::string_view) const) &
                 DataReaderFactory::getReaderForTypeAndExtension<T>)
        .def(fmt::format("has{}Reader", type).c_str(),
             (bool (DataReaderFactory::*)(std::string_view) const) &
                 DataReaderFactory::hasReaderForTypeAndExtension<T>);
}

void exposeDataReaders(pybind11::module& m) {
    namespace py = pybind11;

    py::class_<DataReader>(m, "DataReader")
        .def("clone", &DataReader::clone)
        .def_property_readonly("extensions", &DataReader::getExtensions,
                               py::return_value_policy::reference_internal)
        .def("addExtension", &DataReader::addExtension)
        .def("setOption", &DataReader::setOption)
        .def("getOption", &DataReader::getOption);

    // https://pybind11.readthedocs.io/en/stable/advanced/classes.html#binding-classes-with-template-parameters
    py::class_<DataReaderType<Image>, DataReaderTypeTrampoline<Image>>(m, "ImageDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Image>::readData))
        .def("readData",
             py::overload_cast<std::string_view, MetaDataOwner*>(&DataReaderType<Image>::readData));
    py::class_<DataReaderType<Mesh>, DataReaderTypeTrampoline<Mesh>>(m, "MeshDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Mesh>::readData))
        .def("readData",
             py::overload_cast<std::string_view, MetaDataOwner*>(&DataReaderType<Mesh>::readData));
    py::class_<DataReaderType<Volume>, DataReaderTypeTrampoline<Volume>>(m, "VolumeDataReader")
        .def("readData", py::overload_cast<std::string_view>(&DataReaderType<Volume>::readData))
        .def("readData", py::overload_cast<std::string_view, MetaDataOwner*>(
                             &DataReaderType<Volume>::readData));

    auto fr =
        py::class_<DataReaderFactory>(m, "DataReaderFactory")
            .def(py::init<>())
            .def("create",
                 (std::unique_ptr<DataReader>(DataReaderFactory::*)(const FileExtension&) const) &
                     DataReaderFactory::create)
            .def("create",
                 (std::unique_ptr<DataReader>(DataReaderFactory::*)(std::string_view) const) &
                     DataReaderFactory::create)
            .def("hasKey",
                 (bool (DataReaderFactory::*)(std::string_view) const) & DataReaderFactory::hasKey)
            .def("hasKey", (bool (DataReaderFactory::*)(const FileExtension&) const) &
                               DataReaderFactory::hasKey);
    // No good way of dealing with template return types so we manually define one for each known
    // type.
    // https://github.com/pybind/pybind11/issues/1667#issuecomment-454348004
    // If your module exposes a new reader type it will have to bind getXXXReader.
    exposeFactoryReaderType<Image>(fr, "Image");
    exposeFactoryReaderType<Mesh>(fr, "Mesh");
    exposeFactoryReaderType<Volume>(fr, "Volume");
}

}  // namespace inviwo
<|endoftext|>


<commit_before><commit_msg>Fix missing eye when using CAPI<commit_after><|endoftext|>


<commit_before>#include "interface/usb.h"
#include "util/bytebuffer.h"
#include "util/log.h"
#include "gpio.h"

#ifdef CHIPKIT

#define USB_VBUS_ANALOG_INPUT A0

#endif

#define USB_HANDLE_MAX_WAIT_COUNT 35000

namespace gpio = openxc::gpio;

using openxc::interface::usb::UsbDevice;
using openxc::interface::usb::UsbEndpoint;
using openxc::interface::usb::UsbEndpointDirection;
using openxc::gpio::GPIO_DIRECTION_INPUT;
using openxc::util::bytebuffer::processQueue;

// This is a reference to the last packet read
extern volatile CTRL_TRF_SETUP SetupPkt;
extern UsbDevice USB_DEVICE;
extern bool handleControlRequest(uint8_t);

boolean usbCallback(USB_EVENT event, void *pdata, word size) {
    // initial connection up to configure will be handled by the default
    // callback routine.
    USB_DEVICE.device.DefaultCBEventHandler(event, pdata, size);

    // TODO why can't we use USB_EVENT as the type anymore? rejects
    // EVENT_EP0_REQUEST as a switch case
    switch((int)event) {
    case EVENT_CONFIGURED:
        debug("USB Configured");
        USB_DEVICE.configured = true;

        for(int i = 0; i < ENDPOINT_COUNT; i++) {
            UsbEndpoint* endpoint = &USB_DEVICE.endpoints[i];
            if(endpoint->direction == UsbEndpointDirection::USB_ENDPOINT_DIRECTION_OUT) {
                USB_DEVICE.device.EnableEndpoint(endpoint->address,
                        USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            } else {
                USB_DEVICE.device.EnableEndpoint(endpoint->address,
                        USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            }
        }
        break;

    case EVENT_EP0_REQUEST:
        handleControlRequest(SetupPkt.bRequest);
        break;

    default:
        break;
    }
    return true;
}

void openxc::interface::usb::sendControlMessage(uint8_t* data, uint8_t length) {
    USB_DEVICE.device.EP0SendRAMPtr(data, length, USB_EP0_INCLUDE_ZERO);
}

bool vbusEnabled() {
#ifdef USB_VBUS_ANALOG_INPUT
    return analogRead(USB_VBUS_ANALOG_INPUT) > 100;
#else
    return true;
#endif
}

bool waitForHandle(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    int i = 0;
    while(usbDevice->configured &&
            usbDevice->device.HandleBusy(endpoint->deviceToHostHandle)) {
        ++i;
        if(i > USB_HANDLE_MAX_WAIT_COUNT) {
            // The reason we want to exit this loop early is that if USB is
            // attached and configured, but the host isn't sending an IN
            // requests, we will block here forever. As it is, it still slows
            // down UART transfers quite a bit, so setting configured = false
            // ASAP is important.

            // This can get really noisy when running but I want to leave it in
            // because it' useful to enable when debugging.
            // debug("USB most likely not connected or at least not requesting "
                    // "IN transfers - bailing out of handle waiting");
            return false;
        }
    }
    return true;
}

void openxc::interface::usb::processSendQueue(UsbDevice* usbDevice) {
    if(usbDevice->configured && !vbusEnabled()) {
        debug("USB no longer detected - marking unconfigured");
        usbDevice->configured = false;
        return;
    }

    for(int i = 0; i < ENDPOINT_COUNT; i++) {
        UsbEndpoint* endpoint = &usbDevice->endpoints[i];

        // Don't touch usbDevice->sendBuffer if there's still a pending transfer
        if(!waitForHandle(usbDevice, endpoint)) {
            return;
        }

        while(usbDevice->configured &&
                !QUEUE_EMPTY(uint8_t, &endpoint->queue)) {
            int byteCount = 0;
            while(!QUEUE_EMPTY(uint8_t, &endpoint->queue) &&
                    byteCount < USB_SEND_BUFFER_SIZE) {
                endpoint->sendBuffer[byteCount++] = QUEUE_POP(uint8_t,
                        &endpoint->queue);
            }

            int nextByteIndex = 0;
            while(nextByteIndex < byteCount) {
                // Make sure the USB write is 100% complete before messing with this
                // buffer after we copy the message into it - the Microchip library
                // doesn't copy the data to its own internal buffer. See #171 for
                // background on this issue.
                // TODO instead of dropping, replace POP above with a SNAPSHOT
                // and POP off only exactly how many bytes were sent after the
                // fact.
                // TODO in order for this not to fail too often I had to increase
                // the USB_HANDLE_MAX_WAIT_COUNT. that may be OK since now we have
                // VBUS detection.
                if(!waitForHandle(usbDevice, endpoint)) {
                    debug("USB not responding in a timely fashion, dropped data");
                    return;
                }

                int bytesToTransfer = min(MAX_USB_PACKET_SIZE_BYTES,
                        byteCount - nextByteIndex);
                endpoint->deviceToHostHandle = usbDevice->device.GenWrite(
                        endpoint->address,
                        &endpoint->sendBuffer[nextByteIndex], bytesToTransfer);
                nextByteIndex += bytesToTransfer;
            }
        }
    }
}

void openxc::interface::usb::initialize(UsbDevice* usbDevice) {
    usb::initializeCommon(usbDevice);
    usbDevice->device = USBDevice(usbCallback);
    usbDevice->device.InitializeSystem(false);
#ifdef USB_VBUS_ANALOG_INPUT
    gpio::setDirection(0, USB_VBUS_ANALOG_INPUT, GPIO_DIRECTION_INPUT);
#endif
    debug("Done.");
}

void openxc::interface::usb::deinitialize(UsbDevice* usbDevice) {
    // disable USB (notifies stack we are disabling)
    USBModuleDisable();

    // power off the USB peripheral
    // TODO could not find a ready-made function or macro
    // in the USB library to actually turn off the module.
    // USBModuleDisable() is close to what we want, but it
    // sets the ON bit to 1 for some reason.
    // so, easy solution is just go right to the control register, for now
    U1PWRCCLR = (1 << 0);
}

/* Private: Arm the given endpoint for a read from the device to host.
 *
 * This also puts a NUL char in the beginning of the buffer so you don't get
 * confused that it's still a valid message.
 *
 * device - the CAN USB device to arm the endpoint on
 * endpoint - the endpoint to arm.
 * buffer - the destination buffer for the next OUT transfer.
 */
void armForRead(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    endpoint->receiveBuffer[0] = 0;
    endpoint->hostToDeviceHandle = usbDevice->device.GenRead(
            endpoint->address, (uint8_t*)endpoint->receiveBuffer,
            endpoint->size);
}

void openxc::interface::usb::read(UsbDevice* device, UsbEndpoint* endpoint,
        bool (*callback)(uint8_t*)) {
    if(!device->device.HandleBusy(endpoint->hostToDeviceHandle)) {
        if(endpoint->receiveBuffer[0] != '\0') {
            for(int i = 0; i < endpoint->size; i++) {
                if(!QUEUE_PUSH(uint8_t, &endpoint->receiveQueue,
                            endpoint->receiveBuffer[i])) {
                    debug("Dropped write from host -- queue is full");
                }
            }
            processQueue(&endpoint->receiveQueue, callback);
        }
        armForRead(device, endpoint);
    }
}
<commit_msg>Fix PIC32 build, use new USB attributes.<commit_after>#include "interface/usb.h"
#include "util/bytebuffer.h"
#include "util/log.h"
#include "gpio.h"

#ifdef CHIPKIT

#define USB_VBUS_ANALOG_INPUT A0

#endif

#define USB_HANDLE_MAX_WAIT_COUNT 35000

namespace gpio = openxc::gpio;

using openxc::interface::usb::UsbDevice;
using openxc::interface::usb::UsbEndpoint;
using openxc::interface::usb::UsbEndpointDirection;
using openxc::gpio::GPIO_DIRECTION_INPUT;
using openxc::util::bytebuffer::processQueue;

// This is a reference to the last packet read
extern volatile CTRL_TRF_SETUP SetupPkt;
extern UsbDevice USB_DEVICE;
extern bool handleControlRequest(uint8_t);

boolean usbCallback(USB_EVENT event, void *pdata, word size) {
    // initial connection up to configure will be handled by the default
    // callback routine.
    USB_DEVICE.device.DefaultCBEventHandler(event, pdata, size);

    // TODO why can't we use USB_EVENT as the type anymore? rejects
    // EVENT_EP0_REQUEST as a switch case
    switch((int)event) {
    case EVENT_CONFIGURED:
        debug("USB Configured");
        USB_DEVICE.configured = true;

        for(int i = 0; i < ENDPOINT_COUNT; i++) {
            UsbEndpoint* endpoint = &USB_DEVICE.endpoints[i];
            if(endpoint->direction == UsbEndpointDirection::USB_ENDPOINT_DIRECTION_OUT) {
                USB_DEVICE.device.EnableEndpoint(endpoint->address,
                        USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            } else {
                USB_DEVICE.device.EnableEndpoint(endpoint->address,
                        USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            }
        }
        break;

    case EVENT_EP0_REQUEST:
        handleControlRequest(SetupPkt.bRequest);
        break;

    default:
        break;
    }
    return true;
}

void openxc::interface::usb::sendControlMessage(uint8_t* data, uint8_t length) {
    USB_DEVICE.device.EP0SendRAMPtr(data, length, USB_EP0_INCLUDE_ZERO);
}

bool vbusEnabled() {
#ifdef USB_VBUS_ANALOG_INPUT
    return analogRead(USB_VBUS_ANALOG_INPUT) > 100;
#else
    return true;
#endif
}

bool waitForHandle(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    int i = 0;
    while(usbDevice->configured &&
            usbDevice->device.HandleBusy(endpoint->deviceToHostHandle)) {
        ++i;
        if(i > USB_HANDLE_MAX_WAIT_COUNT) {
            // The reason we want to exit this loop early is that if USB is
            // attached and configured, but the host isn't sending an IN
            // requests, we will block here forever. As it is, it still slows
            // down UART transfers quite a bit, so setting configured = false
            // ASAP is important.

            // This can get really noisy when running but I want to leave it in
            // because it' useful to enable when debugging.
            // debug("USB most likely not connected or at least not requesting "
                    // "IN transfers - bailing out of handle waiting");
            return false;
        }
    }
    return true;
}

void openxc::interface::usb::processSendQueue(UsbDevice* usbDevice) {
    if(usbDevice->configured && !vbusEnabled()) {
        debug("USB no longer detected - marking unconfigured");
        usbDevice->configured = false;
        return;
    }

    for(int i = 0; i < ENDPOINT_COUNT; i++) {
        UsbEndpoint* endpoint = &usbDevice->endpoints[i];

        // Don't touch usbDevice->sendBuffer if there's still a pending transfer
        if(!waitForHandle(usbDevice, endpoint)) {
            return;
        }

        while(usbDevice->configured &&
                !QUEUE_EMPTY(uint8_t, &endpoint->queue)) {
            int byteCount = 0;
            while(!QUEUE_EMPTY(uint8_t, &endpoint->queue) &&
                    byteCount < USB_SEND_BUFFER_SIZE) {
                endpoint->sendBuffer[byteCount++] = QUEUE_POP(uint8_t,
                        &endpoint->queue);
            }

            int nextByteIndex = 0;
            while(nextByteIndex < byteCount) {
                // Make sure the USB write is 100% complete before messing with this
                // buffer after we copy the message into it - the Microchip library
                // doesn't copy the data to its own internal buffer. See #171 for
                // background on this issue.
                // TODO instead of dropping, replace POP above with a SNAPSHOT
                // and POP off only exactly how many bytes were sent after the
                // fact.
                // TODO in order for this not to fail too often I had to increase
                // the USB_HANDLE_MAX_WAIT_COUNT. that may be OK since now we have
                // VBUS detection.
                if(!waitForHandle(usbDevice, endpoint)) {
                    debug("USB not responding in a timely fashion, dropped data");
                    return;
                }

                int bytesToTransfer = min(MAX_USB_PACKET_SIZE_BYTES,
                        byteCount - nextByteIndex);
                endpoint->deviceToHostHandle = usbDevice->device.GenWrite(
                        endpoint->address,
                        &endpoint->sendBuffer[nextByteIndex], bytesToTransfer);
                nextByteIndex += bytesToTransfer;
            }
        }
    }
}

void openxc::interface::usb::initialize(UsbDevice* usbDevice) {
    usb::initializeCommon(usbDevice);
    usbDevice->device = USBDevice(usbCallback);
    usbDevice->device.InitializeSystem(false);
#ifdef USB_VBUS_ANALOG_INPUT
    gpio::setDirection(0, USB_VBUS_ANALOG_INPUT, GPIO_DIRECTION_INPUT);
#endif
    debug("Done.");
}

void openxc::interface::usb::deinitialize(UsbDevice* usbDevice) {
    // disable USB (notifies stack we are disabling)
    USBModuleDisable();

    // power off the USB peripheral
    // TODO could not find a ready-made function or macro
    // in the USB library to actually turn off the module.
    // USBModuleDisable() is close to what we want, but it
    // sets the ON bit to 1 for some reason.
    // so, easy solution is just go right to the control register, for now
    U1PWRCCLR = (1 << 0);
}

/* Private: Arm the given endpoint for a read from the device to host.
 *
 * This also puts a NUL char in the beginning of the buffer so you don't get
 * confused that it's still a valid message.
 *
 * device - the CAN USB device to arm the endpoint on
 * endpoint - the endpoint to arm.
 * buffer - the destination buffer for the next OUT transfer.
 */
void armForRead(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    endpoint->receiveBuffer[0] = 0;
    endpoint->hostToDeviceHandle = usbDevice->device.GenRead(
            endpoint->address, (uint8_t*)endpoint->receiveBuffer,
            endpoint->size);
}

void openxc::interface::usb::read(UsbDevice* device, UsbEndpoint* endpoint,
        bool (*callback)(uint8_t*)) {
    if(!device->device.HandleBusy(endpoint->hostToDeviceHandle)) {
        if(endpoint->receiveBuffer[0] != '\0') {
            for(int i = 0; i < endpoint->size; i++) {
                if(!QUEUE_PUSH(uint8_t, &endpoint->queue,
                            endpoint->receiveBuffer[i])) {
                    debug("Dropped write from host -- queue is full");
                }
            }
            processQueue(&endpoint->queue, callback);
        }
        armForRead(device, endpoint);
    }
}
<|endoftext|>