<commit_before>#include <config.h>
#include <assert.h>
#include <boost/assert.hpp>
#include <dune/common/exceptions.hh>
#include <dune/common/timer.hh>
#include <dune/multiscale/common/righthandside_assembler.hh>
#include <dune/multiscale/msfem/coarse_scale_operator.hh>

#include <dune/stuff/fem/functions/checks.hh>

#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/parameter/configcontainer.hh>
#include <dune/stuff/common/profiler.hh>
#include <dune/stuff/discretefunction/projection/heterogenous.hh>
#include <dune/multiscale/msfem/localproblems/localgridsearch.hh>
#include <sstream>

#include "dune/multiscale/common/dirichletconstraints.hh"
#include "dune/multiscale/common/traits.hh"
#include "dune/multiscale/msfem/msfem_traits.hh"
#include <dune/multiscale/common/output_traits.hh>
#include "msfem_solver.hh"
#include "localsolution_proxy.hh"

namespace Dune {
namespace Multiscale {
namespace MsFEM {

struct LocalOutputTraits {
  //! --------- typedefs and classes for data output -----------------------------------------
  typedef std::tuple<const MsFEMTraits::LocalGridDiscreteFunctionType*> IOTupleType;
  typedef Dune::Fem::DataWriter<MsFEMTraits::LocalGridType, IOTupleType> DataOutputType;
};

void Elliptic_MsFEM_Solver::identify_fine_scale_part(LocalGridList& subgrid_list,
                                                     const DiscreteFunctionType& coarse_msfem_solution,
                                                     DiscreteFunctionType& fine_scale_part) const {
  fine_scale_part.clear();
  const DiscreteFunctionSpace& coarse_space = coarse_msfem_solution.space();
  auto& coarse_indexset = coarse_space.gridPart().grid().leafIndexSet();

  typedef DS::MsFEMProjection<LocalGridSearch> ProjectionType;
  typedef LocalGridSearch<typename MsFEMTraits::LocalGridType::LeafGridView> SearchType;
  typedef LocalsolutionProxy<SearchType> ProxyType;
  typename ProxyType::CorrectionsMapType local_corrections;

  const bool is_simplex_grid = DSG::is_simplex_grid(coarse_space);

  for (auto& coarse_entity : coarse_space) {
    LocalSolutionManager localSolManager(coarse_space, coarse_entity, subgrid_list);
    localSolManager.load();
    auto& localSolutions = localSolManager.getLocalSolutions();
    auto coarse_index = coarse_indexset.index(coarse_entity);
    local_corrections[coarse_index] =
        DSC::make_unique<MsFEMTraits::LocalGridDiscreteFunctionType>("", localSolManager.space());

    auto& local_correction = *local_corrections[coarse_index];
    local_correction.clear();
    auto coarseSolutionLF = coarse_msfem_solution.localFunction(coarse_entity);

    if (is_simplex_grid) {
      BOOST_ASSERT_MSG(localSolutions.size() == Dune::GridSelector::dimgrid,
                       "We should have dim local solutions per coarse element on triangular meshes!");

      JacobianRangeType grad_coarse_msfem_on_entity;
      // We only need the gradient of the coarse scale part on the element, which is a constant.
      coarseSolutionLF.jacobian(coarse_entity.geometry().center(), grad_coarse_msfem_on_entity);

      // get the coarse gradient on T, multiply it with the local correctors and sum it up.
      for (int spaceDimension = 0; spaceDimension < Dune::GridSelector::dimgrid; ++spaceDimension) {
        *localSolutions[spaceDimension] *= grad_coarse_msfem_on_entity[0][spaceDimension];
        local_correction += *localSolutions[spaceDimension];
      }
      BOOST_ASSERT_MSG(false, "no adding of the boundary correctors??");
    } else {
      //! @warning At this point, we assume to have the same types of elements in the coarse and fine grid!
      BOOST_ASSERT_MSG(
          static_cast<long long>(localSolutions.size() - localSolManager.numBoundaryCorrectors()) ==
              static_cast<long long>(coarseSolutionLF.numDofs()),
          "The current implementation relies on having thesame types of elements on coarse and fine level!");
      for (int dof = 0; dof < coarseSolutionLF.numDofs(); ++dof) {
        *localSolutions[dof] *= coarseSolutionLF[dof];
        local_correction += *localSolutions[dof];
      }

      // oversampling : restrict the local correctors to the element T
      // ie set all dofs not "covered" by the coarse cell to 0
      if (DSC_CONFIG_GET("msfem.oversampling_layers", 0)) {
        for (auto& local_entity : localSolManager.space()) {
          const auto& lg_points = localSolManager.space().lagrangePointSet(local_entity);
          const auto& reference_element = DSG::reference_element(coarse_entity);
          const auto& coarse_geometry = coarse_entity.geometry();
          auto entity_local_correction = local_correction.localFunction(local_entity);

          for (const auto lg_i : DSC::valueRange(int(lg_points.size()))) {
            const auto global_lg_point = local_entity.geometry().global(lg_points.point(lg_i));
            const bool covered = reference_element.checkInside(coarse_geometry.local(global_lg_point));
            entity_local_correction[lg_i] = covered ? entity_local_correction[lg_i] : RangeType::value_type(0);
          }
        }
      }

      // add dirichlet corrector
      local_correction += *localSolutions[coarseSolutionLF.numDofs() + 1];
      // substract neumann corrector
      local_correction -= *localSolutions[coarseSolutionLF.numDofs()];

      if (DSC_CONFIG_GET("msfem.local_corrections_vtk_output", false)) {
        LocalOutputTraits::IOTupleType coarse_grid_series(&local_correction);
        const auto elId = coarse_space.gridPart().grid().globalIdSet().id(coarse_entity);
        const std::string name = (boost::format("local_correction_%d_") % elId).str();
        Dune::Multiscale::OutputParameters outputparam;
        outputparam.set_prefix(name);
        auto& grid = localSolManager.space().gridPart().grid();
        LocalOutputTraits::DataOutputType(grid, coarse_grid_series, outputparam).writeData(1.0 /*dummy*/, name);
      }
    }
  }

  SearchType search(coarse_space, subgrid_list);
  ProxyType proxy(local_corrections, coarse_indexset, search);
  ProjectionType::project(proxy, fine_scale_part, search);
  BOOST_ASSERT_MSG(fine_scale_part.dofsValid(), "Fine scale part DOFs need to be valid!");
  //backend storage no longer needed from here on
  DiscreteFunctionIO<MsFEMTraits::LocalGridDiscreteFunctionType>::clear();
}

void Elliptic_MsFEM_Solver::apply(const CommonTraits::DiscreteFunctionSpaceType& coarse_space,
                                  const CommonTraits::DiffusionType& diffusion_op,
                                  const CommonTraits::FirstSourceType& f, DiscreteFunctionType& coarse_scale_part,
                                  DiscreteFunctionType& fine_scale_part, DiscreteFunctionType& solution) const {
  DSC::Profiler::ScopedTiming st("msfem.Elliptic_MsFEM_Solver.apply");
  BOOST_ASSERT_MSG(coarse_scale_part.dofsValid(), "Coarse scale part DOFs need to be valid!");

  DiscreteFunctionType coarse_msfem_solution("Coarse Part MsFEM Solution", coarse_space);
  coarse_msfem_solution.clear();

  LocalGridList subgrid_list(coarse_space);
  //! Solutions are kept in-memory via DiscreteFunctionIO::MemoryBackend by LocalsolutionManagers
  LocalProblemSolver(coarse_space, subgrid_list, diffusion_op).solve_for_all_cells();

  DiscreteFunctionType msfem_rhs("MsFEM right hand side", coarse_space);
  msfem_rhs.clear();
  RightHandSideAssembler::assemble_msfem(coarse_space, f, subgrid_list, msfem_rhs);
  //! define the discrete (elliptic) operator that describes our problem
  CoarseScaleOperator elliptic_msfem_op(coarse_space, subgrid_list, diffusion_op);
  elliptic_msfem_op.apply_inverse(msfem_rhs, coarse_msfem_solution);

  solution.clear();
  Dune::Multiscale::copyDirichletValues(coarse_space, solution);

  //! identify fine scale part of MsFEM solution (including the projection!)
  identify_fine_scale_part(subgrid_list, coarse_msfem_solution, fine_scale_part);

  fine_scale_part.communicate();

  DS::HeterogenousProjection<>::project(coarse_msfem_solution, coarse_scale_part);
  // add coarse and fine scale part to solution
  solution += coarse_scale_part;
  solution += fine_scale_part;
} // solve_dirichlet_zero

} // namespace MsFEM {
} // namespace Multiscale {
} // namespace Dune {
<commit_msg>Added timing for fine scale part identification<commit_after>#include <config.h>
#include <assert.h>
#include <boost/assert.hpp>
#include <dune/common/exceptions.hh>
#include <dune/common/timer.hh>
#include <dune/multiscale/common/righthandside_assembler.hh>
#include <dune/multiscale/msfem/coarse_scale_operator.hh>

#include <dune/stuff/fem/functions/checks.hh>

#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/parameter/configcontainer.hh>
#include <dune/stuff/common/profiler.hh>
#include <dune/stuff/discretefunction/projection/heterogenous.hh>
#include <dune/multiscale/msfem/localproblems/localgridsearch.hh>
#include <sstream>

#include "dune/multiscale/common/dirichletconstraints.hh"
#include "dune/multiscale/common/traits.hh"
#include "dune/multiscale/msfem/msfem_traits.hh"
#include <dune/multiscale/common/output_traits.hh>
#include "msfem_solver.hh"
#include "localsolution_proxy.hh"

namespace Dune {
namespace Multiscale {
namespace MsFEM {

struct LocalOutputTraits {
  //! --------- typedefs and classes for data output -----------------------------------------
  typedef std::tuple<const MsFEMTraits::LocalGridDiscreteFunctionType*> IOTupleType;
  typedef Dune::Fem::DataWriter<MsFEMTraits::LocalGridType, IOTupleType> DataOutputType;
};

void Elliptic_MsFEM_Solver::identify_fine_scale_part(LocalGridList& subgrid_list,
                                                     const DiscreteFunctionType& coarse_msfem_solution,
                                                     DiscreteFunctionType& fine_scale_part) const {
  DSC::Profiler::ScopedTiming st("msfem.idFine");
  fine_scale_part.clear();
  const DiscreteFunctionSpace& coarse_space = coarse_msfem_solution.space();
  auto& coarse_indexset = coarse_space.gridPart().grid().leafIndexSet();

  typedef DS::MsFEMProjection<LocalGridSearch> ProjectionType;
  typedef LocalGridSearch<typename MsFEMTraits::LocalGridType::LeafGridView> SearchType;
  typedef LocalsolutionProxy<SearchType> ProxyType;
  typename ProxyType::CorrectionsMapType local_corrections;

  const bool is_simplex_grid = DSG::is_simplex_grid(coarse_space);

  for (auto& coarse_entity : coarse_space) {
    LocalSolutionManager localSolManager(coarse_space, coarse_entity, subgrid_list);
    localSolManager.load();
    auto& localSolutions = localSolManager.getLocalSolutions();
    auto coarse_index = coarse_indexset.index(coarse_entity);
    local_corrections[coarse_index] =
        DSC::make_unique<MsFEMTraits::LocalGridDiscreteFunctionType>("", localSolManager.space());

    auto& local_correction = *local_corrections[coarse_index];
    local_correction.clear();
    auto coarseSolutionLF = coarse_msfem_solution.localFunction(coarse_entity);

    if (is_simplex_grid) {
      BOOST_ASSERT_MSG(localSolutions.size() == Dune::GridSelector::dimgrid,
                       "We should have dim local solutions per coarse element on triangular meshes!");

      JacobianRangeType grad_coarse_msfem_on_entity;
      // We only need the gradient of the coarse scale part on the element, which is a constant.
      coarseSolutionLF.jacobian(coarse_entity.geometry().center(), grad_coarse_msfem_on_entity);

      // get the coarse gradient on T, multiply it with the local correctors and sum it up.
      for (int spaceDimension = 0; spaceDimension < Dune::GridSelector::dimgrid; ++spaceDimension) {
        *localSolutions[spaceDimension] *= grad_coarse_msfem_on_entity[0][spaceDimension];
        local_correction += *localSolutions[spaceDimension];
      }
      BOOST_ASSERT_MSG(false, "no adding of the boundary correctors??");
    } else {
      //! @warning At this point, we assume to have the same types of elements in the coarse and fine grid!
      BOOST_ASSERT_MSG(
          static_cast<long long>(localSolutions.size() - localSolManager.numBoundaryCorrectors()) ==
              static_cast<long long>(coarseSolutionLF.numDofs()),
          "The current implementation relies on having thesame types of elements on coarse and fine level!");
      for (int dof = 0; dof < coarseSolutionLF.numDofs(); ++dof) {
        *localSolutions[dof] *= coarseSolutionLF[dof];
        local_correction += *localSolutions[dof];
      }

      // oversampling : restrict the local correctors to the element T
      // ie set all dofs not "covered" by the coarse cell to 0
      if (DSC_CONFIG_GET("msfem.oversampling_layers", 0)) {
        for (auto& local_entity : localSolManager.space()) {
          const auto& lg_points = localSolManager.space().lagrangePointSet(local_entity);
          const auto& reference_element = DSG::reference_element(coarse_entity);
          const auto& coarse_geometry = coarse_entity.geometry();
          auto entity_local_correction = local_correction.localFunction(local_entity);

          for (const auto lg_i : DSC::valueRange(int(lg_points.size()))) {
            const auto global_lg_point = local_entity.geometry().global(lg_points.point(lg_i));
            const bool covered = reference_element.checkInside(coarse_geometry.local(global_lg_point));
            entity_local_correction[lg_i] = covered ? entity_local_correction[lg_i] : RangeType::value_type(0);
          }
        }
      }

      // add dirichlet corrector
      local_correction += *localSolutions[coarseSolutionLF.numDofs() + 1];
      // substract neumann corrector
      local_correction -= *localSolutions[coarseSolutionLF.numDofs()];

      if (DSC_CONFIG_GET("msfem.local_corrections_vtk_output", false)) {
        LocalOutputTraits::IOTupleType coarse_grid_series(&local_correction);
        const auto elId = coarse_space.gridPart().grid().globalIdSet().id(coarse_entity);
        const std::string name = (boost::format("local_correction_%d_") % elId).str();
        Dune::Multiscale::OutputParameters outputparam;
        outputparam.set_prefix(name);
        auto& grid = localSolManager.space().gridPart().grid();
        LocalOutputTraits::DataOutputType(grid, coarse_grid_series, outputparam).writeData(1.0 /*dummy*/, name);
      }
    }
  }

  SearchType search(coarse_space, subgrid_list);
  ProxyType proxy(local_corrections, coarse_indexset, search);
  ProjectionType::project(proxy, fine_scale_part, search);
  BOOST_ASSERT_MSG(fine_scale_part.dofsValid(), "Fine scale part DOFs need to be valid!");
  //backend storage no longer needed from here on
  DiscreteFunctionIO<MsFEMTraits::LocalGridDiscreteFunctionType>::clear();
}

void Elliptic_MsFEM_Solver::apply(const CommonTraits::DiscreteFunctionSpaceType& coarse_space,
                                  const CommonTraits::DiffusionType& diffusion_op,
                                  const CommonTraits::FirstSourceType& f, DiscreteFunctionType& coarse_scale_part,
                                  DiscreteFunctionType& fine_scale_part, DiscreteFunctionType& solution) const {
  DSC::Profiler::ScopedTiming st("msfem.Elliptic_MsFEM_Solver.apply");
  BOOST_ASSERT_MSG(coarse_scale_part.dofsValid(), "Coarse scale part DOFs need to be valid!");

  DiscreteFunctionType coarse_msfem_solution("Coarse Part MsFEM Solution", coarse_space);
  coarse_msfem_solution.clear();

  LocalGridList subgrid_list(coarse_space);
  //! Solutions are kept in-memory via DiscreteFunctionIO::MemoryBackend by LocalsolutionManagers
  LocalProblemSolver(coarse_space, subgrid_list, diffusion_op).solve_for_all_cells();

  DiscreteFunctionType msfem_rhs("MsFEM right hand side", coarse_space);
  msfem_rhs.clear();
  RightHandSideAssembler::assemble_msfem(coarse_space, f, subgrid_list, msfem_rhs);
  //! define the discrete (elliptic) operator that describes our problem
  CoarseScaleOperator elliptic_msfem_op(coarse_space, subgrid_list, diffusion_op);
  elliptic_msfem_op.apply_inverse(msfem_rhs, coarse_msfem_solution);

  solution.clear();
  Dune::Multiscale::copyDirichletValues(coarse_space, solution);

  //! identify fine scale part of MsFEM solution (including the projection!)
  identify_fine_scale_part(subgrid_list, coarse_msfem_solution, fine_scale_part);

  fine_scale_part.communicate();

  DS::HeterogenousProjection<>::project(coarse_msfem_solution, coarse_scale_part);
  // add coarse and fine scale part to solution
  solution += coarse_scale_part;
  solution += fine_scale_part;
} // solve_dirichlet_zero

} // namespace MsFEM {
} // namespace Multiscale {
} // namespace Dune {
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: spritecanvas.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 20:52:28 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _CPPCANVAS_SPRITECANVAS_HXX
#define _CPPCANVAS_SPRITECANVAS_HXX

#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _BGFX_VECTOR_B2DSIZE_HXX
#include <basegfx/vector/b2dsize.hxx>
#endif

#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#endif

#ifndef _CPPCANVAS_BITMAPCANVAS_HXX
#include <cppcanvas/bitmapcanvas.hxx>
#endif
#ifndef _CPPCANVAS_SPRITE_HXX
#include <cppcanvas/sprite.hxx>
#endif
#ifndef _CPPCANVAS_CUSTOMSPRITE_HXX
#include <cppcanvas/customsprite.hxx>
#endif

namespace drafts { namespace com { namespace sun { namespace star { namespace rendering
{
    class  XSpriteCanvas;
} } } } }

/* Definition of SpriteCanvas */

namespace cppcanvas
{
    class SpriteCanvas;

    // forward declaration, since cloneSpriteCanvas() also references SpriteCanvas
    typedef ::boost::shared_ptr< ::cppcanvas::SpriteCanvas > SpriteCanvasSharedPtr;

    /** SpriteCanvas interface
     */
    class SpriteCanvas : public virtual BitmapCanvas
    {
    public:
        virtual bool                    updateScreen( bool bUpdateAll ) const = 0;

        virtual CustomSpriteSharedPtr   createCustomSprite( const ::basegfx::B2DSize& ) const = 0;
        virtual SpriteSharedPtr         createClonedSprite( const SpriteSharedPtr& ) const = 0;

        // shared_ptr does not allow for covariant return types
        SpriteCanvasSharedPtr           cloneSpriteCanvas() const
        {
            SpriteCanvasSharedPtr p( ::boost::dynamic_pointer_cast< SpriteCanvas >(this->clone()) );
            OSL_ENSURE(p.get(), "SpriteCanvas::cloneSpriteCanvas(): dynamic cast failed");
            return p;
        }

        virtual ::com::sun::star::uno::Reference<
            ::drafts::com::sun::star::rendering::XSpriteCanvas >    getUNOSpriteCanvas() const = 0;
    };

}

#endif /* _CPPCANVAS_SPRITECANVAS_HXX */
<commit_msg>INTEGRATION: CWS presfixes01 (1.4.6); FILE MERGED 2005/02/16 11:14:25 fs 1.4.6.1: #i42558# drafts.com.sun.star.drawing/rendering/geometry moved to com.sun.star.*<commit_after>/*************************************************************************
 *
 *  $RCSfile: spritecanvas.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-10 13:22:26 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _CPPCANVAS_SPRITECANVAS_HXX
#define _CPPCANVAS_SPRITECANVAS_HXX

#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _BGFX_VECTOR_B2DSIZE_HXX
#include <basegfx/vector/b2dsize.hxx>
#endif

#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#endif

#ifndef _CPPCANVAS_BITMAPCANVAS_HXX
#include <cppcanvas/bitmapcanvas.hxx>
#endif
#ifndef _CPPCANVAS_SPRITE_HXX
#include <cppcanvas/sprite.hxx>
#endif
#ifndef _CPPCANVAS_CUSTOMSPRITE_HXX
#include <cppcanvas/customsprite.hxx>
#endif

namespace com { namespace sun { namespace star { namespace rendering
{
    class  XSpriteCanvas;
} } } }

/* Definition of SpriteCanvas */

namespace cppcanvas
{
    class SpriteCanvas;

    // forward declaration, since cloneSpriteCanvas() also references SpriteCanvas
    typedef ::boost::shared_ptr< ::cppcanvas::SpriteCanvas > SpriteCanvasSharedPtr;

    /** SpriteCanvas interface
     */
    class SpriteCanvas : public virtual BitmapCanvas
    {
    public:
        virtual bool                    updateScreen( bool bUpdateAll ) const = 0;

        virtual CustomSpriteSharedPtr   createCustomSprite( const ::basegfx::B2DSize& ) const = 0;
        virtual SpriteSharedPtr         createClonedSprite( const SpriteSharedPtr& ) const = 0;

        // shared_ptr does not allow for covariant return types
        SpriteCanvasSharedPtr           cloneSpriteCanvas() const
        {
            SpriteCanvasSharedPtr p( ::boost::dynamic_pointer_cast< SpriteCanvas >(this->clone()) );
            OSL_ENSURE(p.get(), "SpriteCanvas::cloneSpriteCanvas(): dynamic cast failed");
            return p;
        }

        virtual ::com::sun::star::uno::Reference<
            ::com::sun::star::rendering::XSpriteCanvas >    getUNOSpriteCanvas() const = 0;
    };

}

#endif /* _CPPCANVAS_SPRITECANVAS_HXX */
<|endoftext|>


<commit_before><commit_msg>log point types as numbers and not as ascii chars with the value of the number<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2011 Zeex
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <algorithm>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "amxcallstack.h"
#include "amxdebuginfo.h"

#include "amx/amx.h"
#include "amx/amxdbg.h"

static bool IsFunctionArgument(const AMXDebugInfo::Symbol &symbol, ucell functionAddress) {
	return symbol.IsLocal() && symbol.GetCodeStartAddress() == functionAddress;
}

class IsArgumentOf : public std::unary_function<AMXDebugInfo::Symbol, bool> {
public:
	IsArgumentOf(ucell function)
		: function_(function) {}
	bool operator()(AMXDebugInfo::Symbol symbol) const {
		return symbol.IsLocal() && symbol.GetCodeStartAddress() == function_;
	}
private:
	ucell function_;
};

static inline const char *GetPublicFunctionName(AMX *amx, ucell address) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);

	if (address == hdr->cip) {
		return "main";
	}

	AMX_FUNCSTUBNT *publics = reinterpret_cast<AMX_FUNCSTUBNT*>(amx->base + hdr->publics);
	AMX_FUNCSTUBNT *natives = reinterpret_cast<AMX_FUNCSTUBNT*>(amx->base + hdr->natives);

	for (AMX_FUNCSTUBNT *p = publics; p < natives; ++p) {
		if (p->address == address) {
			return reinterpret_cast<const char*>(p->nameofs + amx->base);
		}
	}

	return 0;
}

static inline bool IsPublicFunction(AMX *amx, ucell address) {
	return GetPublicFunctionName(amx, address) != 0;
}

static inline bool IsMain(AMX *amx, ucell address) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	return static_cast<cell>(address) == hdr->cip;
}

static inline bool IsAddrOnStack(ucell address, AMX *amx) {
	return (static_cast<cell>(address) >= amx->hlw
	     && static_cast<cell>(address) <  amx->stp);
}

static inline bool IsInCode(ucell address, AMX *amx) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	return static_cast<cell>(address) < hdr->dat - hdr->cod;
}

AMXStackFrame::AMXStackFrame(AMX *amx, ucell frameAddr, const AMXDebugInfo &debugInfo)
	: frameAddr_(frameAddr), retAddr_(0), funAddr_(0)
{
	if (IsAddrOnStack(frameAddr_, amx)) {
		AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);

		ucell data = reinterpret_cast<ucell>(amx->base + hdr->dat);
		ucell code = reinterpret_cast<ucell>(amx->base) + hdr->cod;

		retAddr_ = *(reinterpret_cast<ucell*>(data + frameAddr_) + 1);
		Init(amx, debugInfo);
	}
}

AMXStackFrame::AMXStackFrame(AMX *amx, ucell frameAddr, ucell retAddr, const AMXDebugInfo &debugInfo)
	: frameAddr_(frameAddr), retAddr_(retAddr), funAddr_(0)
{
	Init(amx, debugInfo);
}

AMXStackFrame::AMXStackFrame(AMX *amx, ucell frameAddr, ucell retAddr, ucell funAddr, const AMXDebugInfo &debugInfo)
	: frameAddr_(frameAddr), retAddr_(retAddr), funAddr_(funAddr)
{
	Init(amx, debugInfo);
}

static inline char ToASCII(char c) {
	if (c >= 32 && c <= 126) {
		return c;
	}
	return '\0';
}

static inline char ToASCII(cell c) {
	return ToASCII(static_cast<char>(c & 0xFF));
}

static inline std::string GetPackedAMXString(AMX *amx, cell *string, std::size_t size) {
	std::string s;
	for (std::size_t i = 0; i < size; i++) {
		cell cp = string[i / sizeof(cell)] >> ((sizeof(cell) - i % sizeof(cell) - 1) * 8);
		char cu = ToASCII(cp);
		if (cu == '\0') {
			break;
		}
		s.push_back(cu);
	}

	return s;
}

static inline std::string GetUnpackedAMXString(AMX *amx, cell *string, std::size_t size) {
	std::string s;
	for (std::size_t i = 0; i < size; i++) {
		char c = ToASCII(string[i]);
		if (c == '\0') {
			break;
		}
		s.push_back(c);
	}
	return s;
}

static inline int GetNumArgs(AMX *amx, ucell frame) {
	if (frame > 0) {
		AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
		unsigned char *data = (amx->data != 0) ? amx->data : (amx->base + hdr->dat);
		return *reinterpret_cast<cell*>(data + frame + 2*sizeof(cell)) / sizeof(cell);
	}
	return -1;
}

static std::pair<std::string, bool> GetAMXString(AMX *amx, cell address, std::size_t size) {
	std::pair<std::string, bool> result = std::make_pair("", false);

	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);

	if (address < 0 || address >= hdr->hea - hdr->dat) {
		// The address is not inside the data section...
		return result;
	}

	cell *cstr = reinterpret_cast<cell*>(amx->base + hdr->dat + address);

	if (size == 0) {
		// Size is unknown, copy up to the end of data.
		size = hdr->hea - address;
	}

	if (*reinterpret_cast<ucell*>(cstr) > UNPACKEDMAX) {
		result.first = GetPackedAMXString(amx, cstr, size);
		result.second = true;
	} else {
		result.first = GetUnpackedAMXString(amx, cstr, size);
		result.second = false;
	}

	return result;
}

static cell GetArgument(AMX *amx, int index, cell frame) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	unsigned char *data = amx->data;
	if (data == 0) {
		data = amx->base + hdr->dat;
	}
	return *reinterpret_cast<cell*>(data + frame + (3 + index) * sizeof(cell));
}

static cell NextFrame(AMX *amx, cell frame) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	unsigned char *data = amx->data;
	if (data == 0) {
		data = amx->base + hdr->dat;
	}
	return *reinterpret_cast<cell*>(data + frame);
}

void AMXStackFrame::Init(AMX *amx, const AMXDebugInfo &debugInfo) {
	std::stringstream stream;

	if (debugInfo.IsLoaded()) {
		fun_ = debugInfo.GetFunction(retAddr_);
	}

	if (funAddr_ == 0) {
		if (fun_) {
			funAddr_ = fun_.GetCodeStartAddress();
		} else {
			// Match return address against something in public table.
			if (GetPublicFunctionName(amx, retAddr_) != 0) {
				funAddr_ = retAddr_;
			}
		}
	}

	if (retAddr_ == funAddr_) {
		// The return address isn't real...
		stream << "???????? in ";
	} else {
		stream << std::hex << std::setw(8) << std::setfill('0')
			<< retAddr_ << std::dec << " in ";
	}

	if (fun_) {
		if (IsPublicFunction(amx, funAddr_) && !IsMain(amx, funAddr_)) {
			stream << "public ";
		}
		std::string funTag = debugInfo.GetTagName((fun_).GetTag());
		if (!funTag.empty() && funTag != "_") {
			stream << funTag << ":";
		}
		stream << debugInfo.GetFunctionName(funAddr_);
	} else {
		const char *name = GetPublicFunctionName(amx, funAddr_);
		if (name != 0) {
			stream << "public " << name;
		} else {
			stream << "??"; // unknown function
		}
	}

	stream << " (";

	if (fun_) {
		// Get function parameters.
		std::remove_copy_if(
			debugInfo.GetSymbols().begin(),
			debugInfo.GetSymbols().end(),
			std::back_inserter(args_),
			std::not1(IsArgumentOf(fun_.GetCodeStartAddress()))
		);

		// Order them by address.
		std::sort(args_.begin(), args_.end());

		// Build a comma-separated list of args_ and their values.
		for (std::size_t i = 0; i < args_.size(); i++) {
			AMXDebugInfo::Symbol &arg = args_[i];

			// Argument separator.
			if (i != 0) {
				stream << ", ";
			}

			// For reference arguments print the "&" sign.
			if (arg.IsReference()) {
				stream << "&";
			}

			// Print either "tag:name" or just "name" it has no tag.
			std::string tag = debugInfo.GetTag(arg.GetTag()).GetName() + ":";
			if (tag == "_:") {
				stream << arg.GetName();
			} else {
				stream << tag << arg.GetName();
			}

			// Print argument's value depending on its type and tag.
			cell value = GetArgument(amx, i, NextFrame(amx, frameAddr_));
			if (arg.IsVariable()) {
				if (tag == "bool:") {
					// Boolean.
					stream << "=" << value ? "true" : "false";
				} else if (tag == "Float:") {
					// Floating-point number.
					stream << "=" << std::fixed << std::setprecision(5) << amx_ctof(value);
				} else {
					// Something other...
					stream << "=" << value;
				}
			} else {
				std::vector<AMXDebugInfo::SymbolDim> dims = arg.GetDims();
				if (arg.IsArray() || arg.IsArrayRef()) {
					for (std::size_t i = 0; i < dims.size(); ++i) {
						if (dims[i].GetSize() == 0) {
							stream << "[]";
						} else {
							std::string tag = debugInfo.GetTagName(dims[i].GetTag()) + ":";
							if (tag == "_:") tag.clear();
							stream << "[" << tag << dims[i].GetSize() << "]";
						}
					}
				}

				// For arrays/references we print their AMX address.
				stream << "=@0x" << std::hex << std::setw(8) << std::setfill('0') << value << std::dec;

				// If this is a string argument, get the text.
				if (arg.IsArray() || arg.IsArrayRef()
						&& dims.size() == 1
						&& tag == "_:"
						&& debugInfo.GetTagName(dims[0].GetTag()) == "_")
				{
					std::pair<std::string, bool> s = GetAMXString(amx, value, dims[0].GetSize());
					stream << " ";
					if (s.second) {
						stream << "!"; // packed string
					}
					if (s.first.length() > kMaxString) {
						// The text is too long.
						s.first.replace(kMaxString, s.first.length() - kMaxString, "...");
					}
					stream << "\"" << s.first << "\"";
				}
			}
		}

		//int numArgs = static_cast<int>(args_.size());
		//int numVarArgs = GetNumArgs(amx, frameAddr_) - numArgs;

		//if (numVarArgs > 0) {
		//	if (numArgs != 0) {
		//		stream << ". ";
		//	}
		//	stream << "... <" << numVarArgs << " variable ";
		//	if (numVarArgs == 1) {
		//		stream << "argument";
		//	} else {
		//		stream << "args_";
		//	}
		//	stream << ">";
		//}
	}

	stream << ")";

	if (debugInfo.IsLoaded()) {
		std::string fileName = debugInfo.GetFileName(retAddr_);
		if (!fileName.empty()) {
			stream << " at " << fileName;
		}
		long line = debugInfo.GetLineNumber(retAddr_);
		if (line != 0) {
			stream << ":" << line;
		}
	}

	string_ = stream.str();
}

AMXCallStack::AMXCallStack(AMX *amx, const AMXDebugInfo &debugInfo, ucell topFrame) {
	ucell frm = topFrame;
	if (frm == 0) {
		frm = amx->frm;
	}

	while (frm < static_cast<ucell>(amx->stp)
			&& frm >= static_cast<ucell>(amx->hlw))
	{
		AMXStackFrame frame(amx, frm, debugInfo);
		if (frame.GetReturnAddress() == 0) {
			break;
		} else {
			frames_.push_back(frame);
			frm = NextFrame(amx, frm);
		}
	}
}
<commit_msg>amxcallstack: Show number of variable arguments for variadic functions<commit_after>// Copyright (c) 2011 Zeex
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <algorithm>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "amxcallstack.h"
#include "amxdebuginfo.h"

#include "amx/amx.h"
#include "amx/amxdbg.h"

static bool IsFunctionArgument(const AMXDebugInfo::Symbol &symbol, ucell functionAddress) {
	return symbol.IsLocal() && symbol.GetCodeStartAddress() == functionAddress;
}

class IsArgumentOf : public std::unary_function<AMXDebugInfo::Symbol, bool> {
public:
	IsArgumentOf(ucell function)
		: function_(function) {}
	bool operator()(AMXDebugInfo::Symbol symbol) const {
		return symbol.IsLocal() && symbol.GetCodeStartAddress() == function_;
	}
private:
	ucell function_;
};

static inline const char *GetPublicFunctionName(AMX *amx, ucell address) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);

	if (address == hdr->cip) {
		return "main";
	}

	AMX_FUNCSTUBNT *publics = reinterpret_cast<AMX_FUNCSTUBNT*>(amx->base + hdr->publics);
	AMX_FUNCSTUBNT *natives = reinterpret_cast<AMX_FUNCSTUBNT*>(amx->base + hdr->natives);

	for (AMX_FUNCSTUBNT *p = publics; p < natives; ++p) {
		if (p->address == address) {
			return reinterpret_cast<const char*>(p->nameofs + amx->base);
		}
	}

	return 0;
}

static inline bool IsPublicFunction(AMX *amx, ucell address) {
	return GetPublicFunctionName(amx, address) != 0;
}

static inline bool IsMain(AMX *amx, ucell address) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	return static_cast<cell>(address) == hdr->cip;
}

static inline bool IsAddrOnStack(ucell address, AMX *amx) {
	return (static_cast<cell>(address) >= amx->hlw
	     && static_cast<cell>(address) <  amx->stp);
}

static inline bool IsInCode(ucell address, AMX *amx) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	return static_cast<cell>(address) < hdr->dat - hdr->cod;
}

AMXStackFrame::AMXStackFrame(AMX *amx, ucell frameAddr, const AMXDebugInfo &debugInfo)
	: frameAddr_(frameAddr), retAddr_(0), funAddr_(0)
{
	if (IsAddrOnStack(frameAddr_, amx)) {
		AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);

		ucell data = reinterpret_cast<ucell>(amx->base + hdr->dat);
		ucell code = reinterpret_cast<ucell>(amx->base) + hdr->cod;

		retAddr_ = *(reinterpret_cast<ucell*>(data + frameAddr_) + 1);
		Init(amx, debugInfo);
	}
}

AMXStackFrame::AMXStackFrame(AMX *amx, ucell frameAddr, ucell retAddr, const AMXDebugInfo &debugInfo)
	: frameAddr_(frameAddr), retAddr_(retAddr), funAddr_(0)
{
	Init(amx, debugInfo);
}

AMXStackFrame::AMXStackFrame(AMX *amx, ucell frameAddr, ucell retAddr, ucell funAddr, const AMXDebugInfo &debugInfo)
	: frameAddr_(frameAddr), retAddr_(retAddr), funAddr_(funAddr)
{
	Init(amx, debugInfo);
}

static inline char ToASCII(char c) {
	if (c >= 32 && c <= 126) {
		return c;
	}
	return '\0';
}

static inline char ToASCII(cell c) {
	return ToASCII(static_cast<char>(c & 0xFF));
}

static inline std::string GetPackedAMXString(AMX *amx, cell *string, std::size_t size) {
	std::string s;
	for (std::size_t i = 0; i < size; i++) {
		cell cp = string[i / sizeof(cell)] >> ((sizeof(cell) - i % sizeof(cell) - 1) * 8);
		char cu = ToASCII(cp);
		if (cu == '\0') {
			break;
		}
		s.push_back(cu);
	}

	return s;
}

static inline std::string GetUnpackedAMXString(AMX *amx, cell *string, std::size_t size) {
	std::string s;
	for (std::size_t i = 0; i < size; i++) {
		char c = ToASCII(string[i]);
		if (c == '\0') {
			break;
		}
		s.push_back(c);
	}
	return s;
}

static inline int GetNumArgs(AMX *amx, ucell frame) {
	if (frame > 0) {
		AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
		unsigned char *data = (amx->data != 0) ? amx->data : (amx->base + hdr->dat);
		return *reinterpret_cast<cell*>(data + frame + 2*sizeof(cell)) / sizeof(cell);
	}
	return -1;
}

static std::pair<std::string, bool> GetAMXString(AMX *amx, cell address, std::size_t size) {
	std::pair<std::string, bool> result = std::make_pair("", false);

	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);

	if (address < 0 || address >= hdr->hea - hdr->dat) {
		// The address is not inside the data section...
		return result;
	}

	cell *cstr = reinterpret_cast<cell*>(amx->base + hdr->dat + address);

	if (size == 0) {
		// Size is unknown, copy up to the end of data.
		size = hdr->hea - address;
	}

	if (*reinterpret_cast<ucell*>(cstr) > UNPACKEDMAX) {
		result.first = GetPackedAMXString(amx, cstr, size);
		result.second = true;
	} else {
		result.first = GetUnpackedAMXString(amx, cstr, size);
		result.second = false;
	}

	return result;
}

static cell GetArgument(AMX *amx, int index, cell frame) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	unsigned char *data = amx->data;
	if (data == 0) {
		data = amx->base + hdr->dat;
	}
	return *reinterpret_cast<cell*>(data + frame + (3 + index) * sizeof(cell));
}

static cell NextFrame(AMX *amx, cell frame) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	unsigned char *data = amx->data;
	if (data == 0) {
		data = amx->base + hdr->dat;
	}
	return *reinterpret_cast<cell*>(data + frame);
}

void AMXStackFrame::Init(AMX *amx, const AMXDebugInfo &debugInfo) {
	std::stringstream stream;

	if (debugInfo.IsLoaded()) {
		fun_ = debugInfo.GetFunction(retAddr_);
	}

	if (funAddr_ == 0) {
		if (fun_) {
			funAddr_ = fun_.GetCodeStartAddress();
		} else {
			// Match return address against something in public table.
			if (GetPublicFunctionName(amx, retAddr_) != 0) {
				funAddr_ = retAddr_;
			}
		}
	}

	if (retAddr_ == funAddr_) {
		// The return address isn't real...
		stream << "???????? in ";
	} else {
		stream << std::hex << std::setw(8) << std::setfill('0')
			<< retAddr_ << std::dec << " in ";
	}

	if (fun_) {
		if (IsPublicFunction(amx, funAddr_) && !IsMain(amx, funAddr_)) {
			stream << "public ";
		}
		std::string funTag = debugInfo.GetTagName((fun_).GetTag());
		if (!funTag.empty() && funTag != "_") {
			stream << funTag << ":";
		}
		stream << debugInfo.GetFunctionName(funAddr_);
	} else {
		const char *name = GetPublicFunctionName(amx, funAddr_);
		if (name != 0) {
			stream << "public " << name;
		} else {
			stream << "??"; // unknown function
		}
	}

	stream << " (";

	if (fun_) {
		// Get function parameters.
		std::remove_copy_if(
			debugInfo.GetSymbols().begin(),
			debugInfo.GetSymbols().end(),
			std::back_inserter(args_),
			std::not1(IsArgumentOf(fun_.GetCodeStartAddress()))
		);

		// Order them by address.
		std::sort(args_.begin(), args_.end());

		// Build a comma-separated list of args_ and their values.
		for (std::size_t i = 0; i < args_.size(); i++) {
			AMXDebugInfo::Symbol &arg = args_[i];

			// Argument separator.
			if (i != 0) {
				stream << ", ";
			}

			// For reference arguments print the "&" sign.
			if (arg.IsReference()) {
				stream << "&";
			}

			// Print either "tag:name" or just "name" it has no tag.
			std::string tag = debugInfo.GetTag(arg.GetTag()).GetName() + ":";
			if (tag == "_:") {
				stream << arg.GetName();
			} else {
				stream << tag << arg.GetName();
			}

			// Print argument's value depending on its type and tag.
			cell value = GetArgument(amx, i, NextFrame(amx, frameAddr_));
			if (arg.IsVariable()) {
				if (tag == "bool:") {
					// Boolean.
					stream << "=" << value ? "true" : "false";
				} else if (tag == "Float:") {
					// Floating-point number.
					stream << "=" << std::fixed << std::setprecision(5) << amx_ctof(value);
				} else {
					// Something other...
					stream << "=" << value;
				}
			} else {
				std::vector<AMXDebugInfo::SymbolDim> dims = arg.GetDims();
				if (arg.IsArray() || arg.IsArrayRef()) {
					for (std::size_t i = 0; i < dims.size(); ++i) {
						if (dims[i].GetSize() == 0) {
							stream << "[]";
						} else {
							std::string tag = debugInfo.GetTagName(dims[i].GetTag()) + ":";
							if (tag == "_:") tag.clear();
							stream << "[" << tag << dims[i].GetSize() << "]";
						}
					}
				}

				// For arrays/references we print their AMX address.
				stream << "=@0x" << std::hex << std::setw(8) << std::setfill('0') << value << std::dec;

				// If this is a string argument, get the text.
				if (arg.IsArray() || arg.IsArrayRef()
						&& dims.size() == 1
						&& tag == "_:"
						&& debugInfo.GetTagName(dims[0].GetTag()) == "_")
				{
					std::pair<std::string, bool> s = GetAMXString(amx, value, dims[0].GetSize());
					stream << " ";
					if (s.second) {
						stream << "!"; // packed string
					}
					if (s.first.length() > kMaxString) {
						// The text is too long.
						s.first.replace(kMaxString, s.first.length() - kMaxString, "...");
					}
					stream << "\"" << s.first << "\"";
				}
			}
		}

		int numArgs = static_cast<int>(args_.size());
		int numVarArgs = GetNumArgs(amx, NextFrame(amx, frameAddr_)) - numArgs;

		if (numVarArgs > 0) {
			if (numArgs != 0) {
				stream << ", ";
			}
			stream << "... <" << numVarArgs << " variable ";
			if (numVarArgs == 1) {
				stream << "argument";
			} else {
				stream << "arguments";
			}
			stream << ">";
		}
	}

	stream << ")";

	if (debugInfo.IsLoaded()) {
		std::string fileName = debugInfo.GetFileName(retAddr_);
		if (!fileName.empty()) {
			stream << " at " << fileName;
		}
		long line = debugInfo.GetLineNumber(retAddr_);
		if (line != 0) {
			stream << ":" << line;
		}
	}

	string_ = stream.str();
}

AMXCallStack::AMXCallStack(AMX *amx, const AMXDebugInfo &debugInfo, ucell topFrame) {
	ucell frm = topFrame;
	if (frm == 0) {
		frm = amx->frm;
	}

	while (frm < static_cast<ucell>(amx->stp)
			&& frm >= static_cast<ucell>(amx->hlw))
	{
		AMXStackFrame frame(amx, frm, debugInfo);
		if (frame.GetReturnAddress() == 0) {
			break;
		} else {
			frames_.push_back(frame);
			frm = NextFrame(amx, frm);
		}
	}
}
<|endoftext|>


<commit_before>/// HEADER
#include <csapex_tutorial/tutorial_message.h>

/// PROJECT
#include <csapex/utility/assert.h>
#include <csapex/utility/register_msg.h>

CSAPEX_REGISTER_MESSAGE(csapex::connection_types::TutorialMessage)

using namespace csapex;
using namespace connection_types;

TutorialMessage::TutorialMessage()
    : MessageTemplate<bool, TutorialMessage>("/", 0)
{}

/// YAML
namespace YAML {
Node convert<csapex::connection_types::TutorialMessage>::encode(const csapex::connection_types::TutorialMessage& rhs)
{
    Node node = convert<csapex::connection_types::Message>::encode(rhs);
    node["value"] = rhs.value;
    return node;
}

bool convert<csapex::connection_types::TutorialMessage>::decode(const Node& node, csapex::connection_types::TutorialMessage& rhs)
{
    if(!node.IsMap()) {
        return false;
    }
    convert<csapex::connection_types::Message>::decode(node, rhs);
    rhs.value = node["value"].as<bool>();
    return true;
}
}
<commit_msg>Demonstrate message versioning<commit_after>/// HEADER
#include <csapex_tutorial/tutorial_message.h>

/// PROJECT
#include <csapex/utility/assert.h>
#include <csapex/utility/register_msg.h>

CSAPEX_REGISTER_MESSAGE(csapex::connection_types::TutorialMessage)

using namespace csapex;
using namespace connection_types;

TutorialMessage::TutorialMessage()
    : MessageTemplate<bool, TutorialMessage>("/", 0)
{}

/// YAML
namespace YAML {
Node convert<csapex::connection_types::TutorialMessage>::encode(const csapex::connection_types::TutorialMessage& rhs)
{
    Node node = convert<csapex::connection_types::Message>::encode(rhs, {2, 0, 0});
    node["value2"] = rhs.value;

    return node;
}

bool convert<csapex::connection_types::TutorialMessage>::decode(const Node& node, csapex::connection_types::TutorialMessage& rhs)
{
    if(!node.IsMap()) {
        return false;
    }
    Message::Version version = convert<csapex::connection_types::Message>::decode(node, rhs);
    if(version < Message::Version{2, 0, 0}) {
        rhs.value = node["value"].as<bool>();
    } else {
        rhs.value = node["value2"].as<bool>();
    }

    return true;
}
}
<|endoftext|>


<commit_before>#include "S25FL208K.h"
#include <SPI.h>

S25FL208K::S25FL208K(uint8_t csPin){
  SPI.begin();
  mCsPin = csPin;
  pinMode(mCsPin, OUTPUT);
  digitalWrite(mCsPin, 1); // active low, start disabled
}

// returns dynamic memory
// therefore needs a delete[] call on the pointer when done
uint8_t* S25FL208K::sendCommand(uint8_t command, uint8_t bytesToRead){
  uint8_t* result = NULL;
  digitalWrite(mCsPin, 0);
  SPI.transfer(command);
  if (bytesToRead > 0){
    result = new uint8_t[bytesToRead];
    for (int i = 0; i<bytesToRead; i++){
      result[i] = SPI.transfer(DUMMY_VALUE);
    }
  }
  digitalWrite(mCsPin, 1);
  return result;
}

uint8_t S25FL208K::readStatus(){
  uint8_t* result = NULL;
  uint8_t output = 0;
  result = sendCommand(READ_STATUS_REG, 1);
  output = result[0];
  delete[] result;
  return output;
}

void S25FL208K::writeEnable(void){
  sendCommand(WRITE_ENABLE);
}

void S25FL208K::writeDisable(void){
  sendCommand(WRITE_DISABLE);
}

bool S25FL208K::getWIP(void){
  return (this->readStatus() & WIP_MASK);
}

bool S25FL208K::readData(uint32_t address, uint32_t numBytes, uint8_t* &result){
  // check WIP bit
  if (this->getWIP()){
    return false;
  }

  digitalWrite(mCsPin, 0);
  // transfer the address as 3 bytes
  SPI.transfer(READ_DATA);
  SPI.transfer(uint8_t(0xFF & (address>>16)));
  SPI.transfer(uint8_t(0xFF & (address>>8)));
  SPI.transfer(uint8_t(0xFF & address));

  // read the data into result
  for(int i = 0; i<numBytes; i++){
    result[i] = SPI.transfer(DUMMY_VALUE);
  }
  // end transfer
  digitalWrite(mCsPin, 1);
  return true;
}

bool S25FL208K::storeData(uint32_t address, uint8_t numBytes, uint8_t* &data){
  // check WIP bit
  if (this->getWIP()){
    return false;
  }

  // check page erased
  bool allOnes = true;
  uint8_t tempResult = new uint8_t[numBytes];
  this->readData(address, numBytes, tempResult);
  for (int i = 0; i<numBytes; i++){
    if (tempResult[i]!=0xFF){
      allOnes = false;
    }
  }
  delete[] tempResult;

  if (!allOnes){
    return false;
  }

  // set WRITE_ENABLE
  this->writeEnable();

  digitalWrite(mCsPin, 0);
  // send address
  SPI.transfer(PAGE_PROGRAM);
  SPI.transfer(uint8_t(0xFF & (address>>16)));
  SPI.transfer(uint8_t(0xFF & (address>>8)));
  SPI.transfer(uint8_t(0xFF & address));
  //send data
  for(int i = 0; i<numBytes; i++){
    SPI.transfer(data[i]);
  }

  digitalWrite(mCsPin, 1);

  return true;
}

bool S25FL208K::chipErase(void){
  // check WIP bit
  if (this->getWIP()){
    return false;
  }
  this->sendCommand(CHIP_ERASE);
  return true;
}

bool S25FL208K::sectorErase(uint32_t address){
  // check WIP bit
  if (this->getWIP()){
    return false;
  }

  digitalWrite(mCsPin, 0);
  // transfer the address as 3 bytes
  SPI.transfer(SECTOR_ERASE);
  SPI.transfer(uint8_t(0xFF & (address>>16)));
  SPI.transfer(uint8_t(0xFF & (address>>8)));
  SPI.transfer(uint8_t(0xFF & address));
  digitalWrite(mCsPin, 1);

  return true;
}

bool S25FL208K::blockErase(uint32_t address){
  // check WIP bit
  if (this->getWIP()){
    return false;
  }

  digitalWrite(mCsPin, 0);
  // transfer the address as 3 bytes
  SPI.transfer(BLOCK_ERASE);
  SPI.transfer(uint8_t(0xFF & (address>>16)));
  SPI.transfer(uint8_t(0xFF & (address>>8)));
  SPI.transfer(uint8_t(0xFF & address));
  digitalWrite(mCsPin, 1);

  return true;
}
<commit_msg>fixed missing pointer<commit_after>#include "S25FL208K.h"
#include <SPI.h>

S25FL208K::S25FL208K(uint8_t csPin){
  SPI.begin();
  mCsPin = csPin;
  pinMode(mCsPin, OUTPUT);
  digitalWrite(mCsPin, 1); // active low, start disabled
}

// returns dynamic memory
// therefore needs a delete[] call on the pointer when done
uint8_t* S25FL208K::sendCommand(uint8_t command, uint8_t bytesToRead){
  uint8_t* result = NULL;
  digitalWrite(mCsPin, 0);
  SPI.transfer(command);
  if (bytesToRead > 0){
    result = new uint8_t[bytesToRead];
    for (int i = 0; i<bytesToRead; i++){
      result[i] = SPI.transfer(DUMMY_VALUE);
    }
  }
  digitalWrite(mCsPin, 1);
  return result;
}

uint8_t S25FL208K::readStatus(){
  uint8_t* result = NULL;
  uint8_t output = 0;
  result = sendCommand(READ_STATUS_REG, 1);
  output = result[0];
  delete[] result;
  return output;
}

void S25FL208K::writeEnable(void){
  sendCommand(WRITE_ENABLE);
}

void S25FL208K::writeDisable(void){
  sendCommand(WRITE_DISABLE);
}

bool S25FL208K::getWIP(void){
  return (this->readStatus() & WIP_MASK);
}

bool S25FL208K::readData(uint32_t address, uint32_t numBytes, uint8_t* &result){
  // check WIP bit
  if (this->getWIP()){
    return false;
  }

  digitalWrite(mCsPin, 0);
  // transfer the address as 3 bytes
  SPI.transfer(READ_DATA);
  SPI.transfer(uint8_t(0xFF & (address>>16)));
  SPI.transfer(uint8_t(0xFF & (address>>8)));
  SPI.transfer(uint8_t(0xFF & address));

  // read the data into result
  for(int i = 0; i<numBytes; i++){
    result[i] = SPI.transfer(DUMMY_VALUE);
  }
  // end transfer
  digitalWrite(mCsPin, 1);
  return true;
}

bool S25FL208K::storeData(uint32_t address, uint8_t numBytes, uint8_t* &data){
  // check WIP bit
  if (this->getWIP()){
    return false;
  }

  // check page erased
  bool allOnes = true;
  uint8_t* tempResult = new uint8_t[numBytes];
  this->readData(address, numBytes, tempResult);
  for (int i = 0; i<numBytes; i++){
    if (tempResult[i]!=0xFF){
      allOnes = false;
    }
  }
  delete[] tempResult;

  if (!allOnes){
    return false;
  }

  // set WRITE_ENABLE
  this->writeEnable();

  digitalWrite(mCsPin, 0);
  // send address
  SPI.transfer(PAGE_PROGRAM);
  SPI.transfer(uint8_t(0xFF & (address>>16)));
  SPI.transfer(uint8_t(0xFF & (address>>8)));
  SPI.transfer(uint8_t(0xFF & address));
  //send data
  for(int i = 0; i<numBytes; i++){
    SPI.transfer(data[i]);
  }

  digitalWrite(mCsPin, 1);

  return true;
}

bool S25FL208K::chipErase(void){
  // check WIP bit
  if (this->getWIP()){
    return false;
  }
  this->sendCommand(CHIP_ERASE);
  return true;
}

bool S25FL208K::sectorErase(uint32_t address){
  // check WIP bit
  if (this->getWIP()){
    return false;
  }

  digitalWrite(mCsPin, 0);
  // transfer the address as 3 bytes
  SPI.transfer(SECTOR_ERASE);
  SPI.transfer(uint8_t(0xFF & (address>>16)));
  SPI.transfer(uint8_t(0xFF & (address>>8)));
  SPI.transfer(uint8_t(0xFF & address));
  digitalWrite(mCsPin, 1);

  return true;
}

bool S25FL208K::blockErase(uint32_t address){
  // check WIP bit
  if (this->getWIP()){
    return false;
  }

  digitalWrite(mCsPin, 0);
  // transfer the address as 3 bytes
  SPI.transfer(BLOCK_ERASE);
  SPI.transfer(uint8_t(0xFF & (address>>16)));
  SPI.transfer(uint8_t(0xFF & (address>>8)));
  SPI.transfer(uint8_t(0xFF & address));
  digitalWrite(mCsPin, 1);

  return true;
}
<|endoftext|>


<commit_before>#include "Pointer.h"
#include "PSS.h"

namespace dg {
namespace analysis {

// nodes representing NULL and unknown memory
PSSNode NULLPTR_LOC(pss::NULLPTR);
PSSNode *NULLPTR = &NULLPTR_LOC;
PSSNode UNKNOWN_MEMLOC(pss::UNKNOWN_MEMLOC);
PSSNode *UNKNOWN_MEMORY = &UNKNOWN_MEMLOC;

// pointers to those memory
const Pointer PointerUnknown(UNKNOWN_MEMORY, UNKNOWN_OFFSET);
const Pointer PointerNull(NULLPTR, 0);

using namespace pss;

// replace all pointers to given target with one
// to that target, but UNKNOWN_OFFSET
bool PSSNode::addPointsToUnknownOffset(PSSNode *target)
{
    bool changed = false;
    // FIXME: use equal range, it is much faster
    for (auto I = pointsTo.begin(), E = pointsTo.end(); I != E;) {
        auto cur = I++;
        if (cur->target == target && !cur->offset.isUnknown()) {
            pointsTo.erase(cur);
            changed = true;
        }
    }

    changed |= addPointsTo(target, UNKNOWN_OFFSET);
    return changed;
}

bool PSS::processLoad(PSSNode *node)
{
    bool changed = false;
    PSSNode *operand = node->getOperand(0);

    if (operand->pointsTo.empty())
        return errorEmptyPointsTo(node, operand);

    for (const Pointer& ptr : operand->pointsTo) {
        PSSNode *target = ptr.target;
        assert(target && "Got nullptr as target");

        // find memory objects holding relevant points-to
        // information
        std::vector<MemoryObject *> objects;
        getMemoryObjects(node, target, objects);

        // no objects found for this target? That is
        // load from unknown memory
        if (objects.empty()) {
            if (target->isZeroInitialized())
                // if the memory is zero initialized, then everything
                // is fine, we add nullptr
                changed |= node->addPointsTo(dg::analysis::NULLPTR);
            else
                errorEmptyPointsTo(node, target);

            continue;
        }

        for (MemoryObject *o : objects) {
            // load from empty points-to set
            // - that is load from unknown memory
            if (!o->pointsTo.count(ptr.offset)) {
                // if the memory is zero initialized, then everything
                // is fine, we add nullptr
                if (target->isZeroInitialized())
                    changed |= node->addPointsTo(dg::analysis::NULLPTR);
                else
                    errorEmptyPointsTo(node, target);

                // we've done everything we could
                continue;
            }

            for (const Pointer& memptr : o->pointsTo[ptr.offset]) {
                changed |= node->addPointsTo(memptr);
            }
        }
    }

    return changed;
}

bool PSS::processNode(PSSNode *node)
{
    bool changed = false;
    std::vector<MemoryObject *> objects;

    switch(node->type) {
        case ALLOC:
        case DYN_ALLOC:
            changed |= node->addPointsTo(node, 0);
            break;
        case LOAD:
            changed |= processLoad(node);
            break;
        case STORE:
            for (const Pointer& ptr : node->getOperand(1)->pointsTo) {
                PSSNode *target = ptr.target;
                assert(target && "Got nullptr as target");

                objects.clear();
                getMemoryObjects(node, target, objects);
                for (MemoryObject *o : objects) {
                    for (const Pointer& to : node->getOperand(0)->pointsTo)
                        changed |= o->addPointsTo(ptr.offset, to);
                }
            }
            break;
        case GEP:
            for (const Pointer& ptr : node->getOperand(0)->pointsTo) {
                uint64_t new_offset = *ptr.offset + *node->offset;
                // in the case the memory has size 0, then every pointer
                // will have unknown offset
                if (new_offset < ptr.target->getSize())
                    changed |= node->addPointsTo(ptr.target, new_offset);
                else
                    changed |= node->addPointsToUnknownOffset(ptr.target);
            }
            break;
        case CAST:
            // cast only copies the pointers
            for (const Pointer& ptr : node->getOperand(0)->pointsTo)
                changed |= node->addPointsTo(ptr);
            break;
        case CONSTANT:
            // maybe warn? It has no sense to insert the constants into the graph.
            // On the other hand it is harmless. We can at least check if it is
            // correctly initialized 8-)
            assert(node->pointsTo.size() == 1
                   && "Constant should have exactly one pointer");
            break;
        case CALL:
        case RETURN:
            break;
        case PHI:
            for (PSSNode *op : node->operands)
                changed |= node->addPointsTo(op->pointsTo);
            break;
        case NOOP:
            // just no op
            break;
        default:
            assert(0 && "Unknown type");
    }

    return changed;
}

} // namespace analysis
} // namespace dg
<commit_msg>PSS gep: don't make offset unknwon when it is 0<commit_after>#include "Pointer.h"
#include "PSS.h"

namespace dg {
namespace analysis {

// nodes representing NULL and unknown memory
PSSNode NULLPTR_LOC(pss::NULLPTR);
PSSNode *NULLPTR = &NULLPTR_LOC;
PSSNode UNKNOWN_MEMLOC(pss::UNKNOWN_MEMLOC);
PSSNode *UNKNOWN_MEMORY = &UNKNOWN_MEMLOC;

// pointers to those memory
const Pointer PointerUnknown(UNKNOWN_MEMORY, UNKNOWN_OFFSET);
const Pointer PointerNull(NULLPTR, 0);

using namespace pss;

// replace all pointers to given target with one
// to that target, but UNKNOWN_OFFSET
bool PSSNode::addPointsToUnknownOffset(PSSNode *target)
{
    bool changed = false;
    // FIXME: use equal range, it is much faster
    for (auto I = pointsTo.begin(), E = pointsTo.end(); I != E;) {
        auto cur = I++;
        if (cur->target == target && !cur->offset.isUnknown()) {
            pointsTo.erase(cur);
            changed = true;
        }
    }

    changed |= addPointsTo(target, UNKNOWN_OFFSET);
    return changed;
}

bool PSS::processLoad(PSSNode *node)
{
    bool changed = false;
    PSSNode *operand = node->getOperand(0);

    if (operand->pointsTo.empty())
        return errorEmptyPointsTo(node, operand);

    for (const Pointer& ptr : operand->pointsTo) {
        PSSNode *target = ptr.target;
        assert(target && "Got nullptr as target");

        // find memory objects holding relevant points-to
        // information
        std::vector<MemoryObject *> objects;
        getMemoryObjects(node, target, objects);

        // no objects found for this target? That is
        // load from unknown memory
        if (objects.empty()) {
            if (target->isZeroInitialized())
                // if the memory is zero initialized, then everything
                // is fine, we add nullptr
                changed |= node->addPointsTo(dg::analysis::NULLPTR);
            else
                errorEmptyPointsTo(node, target);

            continue;
        }

        for (MemoryObject *o : objects) {
            // load from empty points-to set
            // - that is load from unknown memory
            if (!o->pointsTo.count(ptr.offset)) {
                // if the memory is zero initialized, then everything
                // is fine, we add nullptr
                if (target->isZeroInitialized())
                    changed |= node->addPointsTo(dg::analysis::NULLPTR);
                else
                    errorEmptyPointsTo(node, target);

                // we've done everything we could
                continue;
            }

            for (const Pointer& memptr : o->pointsTo[ptr.offset]) {
                changed |= node->addPointsTo(memptr);
            }
        }
    }

    return changed;
}

bool PSS::processNode(PSSNode *node)
{
    bool changed = false;
    std::vector<MemoryObject *> objects;

    switch(node->type) {
        case ALLOC:
        case DYN_ALLOC:
            changed |= node->addPointsTo(node, 0);
            break;
        case LOAD:
            changed |= processLoad(node);
            break;
        case STORE:
            for (const Pointer& ptr : node->getOperand(1)->pointsTo) {
                PSSNode *target = ptr.target;
                assert(target && "Got nullptr as target");

                objects.clear();
                getMemoryObjects(node, target, objects);
                for (MemoryObject *o : objects) {
                    for (const Pointer& to : node->getOperand(0)->pointsTo)
                        changed |= o->addPointsTo(ptr.offset, to);
                }
            }
            break;
        case GEP:
            for (const Pointer& ptr : node->getOperand(0)->pointsTo) {
                uint64_t new_offset = *ptr.offset + *node->offset;
                // in the case the memory has size 0, then every pointer
                // will have unknown offset with the exception that it points
                // to the begining of the memory - then we can use the 0
                if (new_offset == 0 || new_offset < ptr.target->getSize())
                    changed |= node->addPointsTo(ptr.target, new_offset);
                else
                    changed |= node->addPointsToUnknownOffset(ptr.target);
            }
            break;
        case CAST:
            // cast only copies the pointers
            for (const Pointer& ptr : node->getOperand(0)->pointsTo)
                changed |= node->addPointsTo(ptr);
            break;
        case CONSTANT:
            // maybe warn? It has no sense to insert the constants into the graph.
            // On the other hand it is harmless. We can at least check if it is
            // correctly initialized 8-)
            assert(node->pointsTo.size() == 1
                   && "Constant should have exactly one pointer");
            break;
        case CALL:
        case RETURN:
            break;
        case PHI:
            for (PSSNode *op : node->operands)
                changed |= node->addPointsTo(op->pointsTo);
            break;
        case NOOP:
            // just no op
            break;
        default:
            assert(0 && "Unknown type");
    }

    return changed;
}

} // namespace analysis
} // namespace dg
<|endoftext|>


<commit_before>#include "uinput.h"
#include "eventlists/eventlist.h"
#include "string.h"

const char* try_to_find_uinput() {
  static const char* paths[] = {
    "/dev/uinput",
    "/dev/input/uinput",
    "/dev/misc/uinput"
  };
  const int num_paths = 3;
  int i;

  for (i = 0; i < num_paths; i++) {
    if (access(paths[i], F_OK) == 0) {
      return paths[i];
    }
  }
  return nullptr;
}

std::string uinput_devnode(int fd) {
  char buffer[128];
  memset(buffer,0,sizeof(buffer));
  ioctl(fd, UI_GET_SYSNAME(127), &buffer);
  buffer[127] = '\0';
  return std::string("/sys/devices/virtual/input/") + std::string(buffer);
}

void uinput_destroy(int fd) {
  ioctl(fd, UI_DEV_DESTROY);
}

uinput::uinput() {
  filename = try_to_find_uinput();
  if (filename == nullptr) throw - 1;

}

int uinput::make_gamepad(const uinput_ids& ids, bool dpad_as_hat, bool analog_triggers) {
  static int abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY};
  static int key[] = { BTN_SOUTH, BTN_EAST, BTN_NORTH, BTN_WEST, BTN_SELECT, BTN_MODE, BTN_START, BTN_TL, BTN_TR, BTN_THUMBL, BTN_THUMBR, -1};
  struct uinput_user_dev uidev;
  int fd;
  int i;
  //TODO: Read from uinput for rumble events?
  fd = open(filename, O_WRONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("open uinput");
    return -1;
  }
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, ids.device_string.c_str());
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = ids.vendor_id;
  uidev.id.product = ids.product_id;
  uidev.id.version = ids.version_id;

  ioctl(fd, UI_SET_EVBIT, EV_ABS);
  for (i = 0; i < 4; i++) {
    ioctl(fd, UI_SET_ABSBIT, abs[i]);
    uidev.absmin[abs[i]] = -32768;
    uidev.absmax[abs[i]] = 32767;
    uidev.absflat[abs[i]] = 1024;
  }

  if (analog_triggers) {
    ioctl(fd, UI_SET_ABSBIT, ABS_Z);
    uidev.absmin[ABS_Z] = 0;
    uidev.absmax[ABS_Z] = 255;
    uidev.absflat[ABS_Z] = 0;
    ioctl(fd, UI_SET_ABSBIT, ABS_RZ);
    uidev.absmin[ABS_RZ] = 0;
    uidev.absmax[ABS_RZ] = 255;
    uidev.absflat[ABS_RZ] = 0;
  }

  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  for (i = 0; key[i] >= 0; i++) {
    ioctl(fd, UI_SET_KEYBIT, key[i]);
  }

  if (dpad_as_hat) {
    ioctl(fd, UI_SET_ABSBIT, ABS_HAT0X);
    uidev.absmin[ABS_HAT0X] = -1;
    uidev.absmax[ABS_HAT0X] = 1;
    uidev.absflat[ABS_HAT0X] = 0;
    ioctl(fd, UI_SET_ABSBIT, ABS_HAT0Y);
    uidev.absmin[ABS_HAT0Y] = -1;
    uidev.absmax[ABS_HAT0Y] = 1;
    uidev.absflat[ABS_HAT0Y] = 0;
  } else {
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_UP);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_DOWN);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_LEFT);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_RIGHT);
  }
  if (!analog_triggers) {
    ioctl(fd, UI_SET_KEYBIT, BTN_TL2);
    ioctl(fd, UI_SET_KEYBIT, BTN_TR2);
  }

  write(fd, &uidev, sizeof(uidev));
  if (ioctl(fd, UI_DEV_CREATE) < 0)
    perror("uinput device creation");

  lock.lock();
  virtual_nodes.push_back(uinput_devnode(fd));
  lock.unlock();

  return fd;
}

int uinput::make_keyboard(const uinput_ids& ids) {
  struct uinput_user_dev uidev;
  int fd;
  int i;

  fd = open(filename, O_WRONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("\nopen uinput");
    return -1;
  }
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, ids.device_string.c_str());
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = ids.vendor_id;
  uidev.id.product = ids.product_id;
  uidev.id.version = ids.version_id;

  /*Just set all possible keys up to BTN_TASK
   * This should cover all reasonable keyboard and mouse keys.*/
  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  for (i = KEY_ESC; i <= BTN_TASK; i++) {
    ioctl(fd, UI_SET_KEYBIT, i);
  }
  for (i = KEY_OK; i < KEY_KBDINPUTASSIST_CANCEL; i++) {
    ioctl(fd, UI_SET_KEYBIT, i);
  }

  //Set BTN_TOUCH so joydev thinks this a touchscreen.
  ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH);

  /*Set basic mouse events*/
  static int abs[] = { ABS_X, ABS_Y};

  ioctl(fd, UI_SET_EVBIT, EV_ABS);
  for (i = 0; i < 2; i++) {
    ioctl(fd, UI_SET_ABSBIT, abs[i]);
    uidev.absmin[abs[i]] = -32768;
    uidev.absmax[abs[i]] = 32767;
  }

  ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT);

  write(fd, &uidev, sizeof(uidev));
  if (ioctl(fd, UI_DEV_CREATE) < 0)
    perror("uinput device creation");

  lock.lock();
  virtual_nodes.push_back(uinput_devnode(fd));
  lock.unlock();

  return fd;
}

int uinput::make_mouse(const uinput_ids& ids) {
  struct uinput_user_dev uidev;
  int fd;
  int i;

  fd = open(filename, O_WRONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("\nopen uinput");
    return -1;
  }
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, ids.device_string.c_str());
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = ids.vendor_id;
  uidev.id.product = ids.product_id;
  uidev.id.version = ids.version_id;

  //Set Mouse buttons
  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  for (i = BTN_MOUSE; i <= BTN_MIDDLE; i++) {
    ioctl(fd, UI_SET_KEYBIT, i);
  }

  /*Set basic mouse events*/
  static int rel[] = { REL_X, REL_Y};

  ioctl(fd, UI_SET_EVBIT, EV_REL);
  for (i = 0; i < 2; i++) {
    ioctl(fd, UI_SET_RELBIT, rel[i]);
  }

  ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_POINTER);

  write(fd, &uidev, sizeof(uidev));
  if (ioctl(fd, UI_DEV_CREATE) < 0)
    perror("uinput device creation");

  lock.lock();
  virtual_nodes.push_back(uinput_devnode(fd));
  lock.unlock();

  return fd;
}

uinput::~uinput() {
}

bool uinput::node_owned(const std::string& path) const {
  lock.lock();
  for (auto node : virtual_nodes) {
    //Check to see if node is a prefix of this path, if so the path belongs to us.
    auto comp = std::mismatch(node.begin(),node.end(),path.begin());
    if (comp.first == node.end()) {
      lock.unlock();
      return true;
    }
  }
  lock.unlock();
  return false;
}

<commit_msg>set PHYS property so that MG virt devs can be distinguished<commit_after>#include "uinput.h"
#include "eventlists/eventlist.h"
#include "string.h"

const char* try_to_find_uinput() {
  static const char* paths[] = {
    "/dev/uinput",
    "/dev/input/uinput",
    "/dev/misc/uinput"
  };
  const int num_paths = 3;
  int i;

  for (i = 0; i < num_paths; i++) {
    if (access(paths[i], F_OK) == 0) {
      return paths[i];
    }
  }
  return nullptr;
}

std::string uinput_devnode(int fd) {
  char buffer[128];
  memset(buffer,0,sizeof(buffer));
  ioctl(fd, UI_GET_SYSNAME(127), &buffer);
  buffer[127] = '\0';
  if (buffer[0] == '\0')
    return "";
  return std::string("/sys/devices/virtual/input/") + std::string(buffer);
}

void uinput_destroy(int fd) {
  ioctl(fd, UI_DEV_DESTROY);
}

uinput::uinput() {
  filename = try_to_find_uinput();
  if (filename == nullptr) throw - 1;

}

int uinput::make_gamepad(const uinput_ids& ids, bool dpad_as_hat, bool analog_triggers) {
  static int abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY};
  static int key[] = { BTN_SOUTH, BTN_EAST, BTN_NORTH, BTN_WEST, BTN_SELECT, BTN_MODE, BTN_START, BTN_TL, BTN_TR, BTN_THUMBL, BTN_THUMBR, -1};
  struct uinput_user_dev uidev;
  int fd;
  int i;
  //TODO: Read from uinput for rumble events?
  fd = open(filename, O_WRONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("open uinput");
    return -1;
  }
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, ids.device_string.c_str());
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = ids.vendor_id;
  uidev.id.product = ids.product_id;
  uidev.id.version = ids.version_id;

  ioctl(fd, UI_SET_EVBIT, EV_ABS);
  for (i = 0; i < 4; i++) {
    ioctl(fd, UI_SET_ABSBIT, abs[i]);
    uidev.absmin[abs[i]] = -32768;
    uidev.absmax[abs[i]] = 32767;
    uidev.absflat[abs[i]] = 1024;
  }

  if (analog_triggers) {
    ioctl(fd, UI_SET_ABSBIT, ABS_Z);
    uidev.absmin[ABS_Z] = 0;
    uidev.absmax[ABS_Z] = 255;
    uidev.absflat[ABS_Z] = 0;
    ioctl(fd, UI_SET_ABSBIT, ABS_RZ);
    uidev.absmin[ABS_RZ] = 0;
    uidev.absmax[ABS_RZ] = 255;
    uidev.absflat[ABS_RZ] = 0;
  }

  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  for (i = 0; key[i] >= 0; i++) {
    ioctl(fd, UI_SET_KEYBIT, key[i]);
  }

  if (dpad_as_hat) {
    ioctl(fd, UI_SET_ABSBIT, ABS_HAT0X);
    uidev.absmin[ABS_HAT0X] = -1;
    uidev.absmax[ABS_HAT0X] = 1;
    uidev.absflat[ABS_HAT0X] = 0;
    ioctl(fd, UI_SET_ABSBIT, ABS_HAT0Y);
    uidev.absmin[ABS_HAT0Y] = -1;
    uidev.absmax[ABS_HAT0Y] = 1;
    uidev.absflat[ABS_HAT0Y] = 0;
  } else {
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_UP);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_DOWN);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_LEFT);
    ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_RIGHT);
  }
  if (!analog_triggers) {
    ioctl(fd, UI_SET_KEYBIT, BTN_TL2);
    ioctl(fd, UI_SET_KEYBIT, BTN_TR2);
  }
  ioctl(fd, UI_SET_PHYS, "moltengamepad");

  write(fd, &uidev, sizeof(uidev));
  if (ioctl(fd, UI_DEV_CREATE) < 0)
    perror("uinput device creation");

  lock.lock();
  virtual_nodes.push_back(uinput_devnode(fd));
  lock.unlock();

  return fd;
}

int uinput::make_keyboard(const uinput_ids& ids) {
  struct uinput_user_dev uidev;
  int fd;
  int i;

  fd = open(filename, O_WRONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("\nopen uinput");
    return -1;
  }
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, ids.device_string.c_str());
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = ids.vendor_id;
  uidev.id.product = ids.product_id;
  uidev.id.version = ids.version_id;

  /*Just set all possible keys up to BTN_TASK
   * This should cover all reasonable keyboard and mouse keys.*/
  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  for (i = KEY_ESC; i <= BTN_TASK; i++) {
    ioctl(fd, UI_SET_KEYBIT, i);
  }
  for (i = KEY_OK; i < KEY_KBDINPUTASSIST_CANCEL; i++) {
    ioctl(fd, UI_SET_KEYBIT, i);
  }

  //Set BTN_TOUCH so joydev thinks this a touchscreen.
  ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH);

  /*Set basic mouse events*/
  static int abs[] = { ABS_X, ABS_Y};

  ioctl(fd, UI_SET_EVBIT, EV_ABS);
  for (i = 0; i < 2; i++) {
    ioctl(fd, UI_SET_ABSBIT, abs[i]);
    uidev.absmin[abs[i]] = -32768;
    uidev.absmax[abs[i]] = 32767;
  }

  ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT);
  ioctl(fd, UI_SET_PHYS, "moltengamepad");

  write(fd, &uidev, sizeof(uidev));
  if (ioctl(fd, UI_DEV_CREATE) < 0)
    perror("uinput device creation");

  lock.lock();
  virtual_nodes.push_back(uinput_devnode(fd));
  lock.unlock();

  return fd;
}

int uinput::make_mouse(const uinput_ids& ids) {
  struct uinput_user_dev uidev;
  int fd;
  int i;

  fd = open(filename, O_WRONLY | O_NONBLOCK);
  if (fd < 0) {
    perror("\nopen uinput");
    return -1;
  }
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, ids.device_string.c_str());
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor = ids.vendor_id;
  uidev.id.product = ids.product_id;
  uidev.id.version = ids.version_id;

  //Set Mouse buttons
  ioctl(fd, UI_SET_EVBIT, EV_KEY);
  for (i = BTN_MOUSE; i <= BTN_MIDDLE; i++) {
    ioctl(fd, UI_SET_KEYBIT, i);
  }

  /*Set basic mouse events*/
  static int rel[] = { REL_X, REL_Y};

  ioctl(fd, UI_SET_EVBIT, EV_REL);
  for (i = 0; i < 2; i++) {
    ioctl(fd, UI_SET_RELBIT, rel[i]);
  }

  ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_POINTER);
  ioctl(fd, UI_SET_PHYS, "moltengamepad");

  write(fd, &uidev, sizeof(uidev));
  if (ioctl(fd, UI_DEV_CREATE) < 0)
    perror("uinput device creation");

  lock.lock();
  virtual_nodes.push_back(uinput_devnode(fd));
  lock.unlock();

  return fd;
}

uinput::~uinput() {
}

bool uinput::node_owned(const std::string& path) const {
  lock.lock();
  for (auto node : virtual_nodes) {
    //Check to see if node is a prefix of this path, if so the path belongs to us.
    auto comp = std::mismatch(node.begin(),node.end(),path.begin());
    if (comp.first == node.end()) {
      lock.unlock();
      return true;
    }
  }
  lock.unlock();
  return false;
}

<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////
// File:        renderer.cpp
// Description: Rendering interface to inject into TessBaseAPI
//
// (C) Copyright 2011, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////

#ifdef HAVE_CONFIG_H
#  include "config_auto.h"
#endif
#include <tesseract/baseapi.h>
#include <tesseract/renderer.h>
#include <cstring>
#include <memory>     // std::unique_ptr
#include <string>     // std::string
#include "serialis.h" // Serialize

namespace tesseract {

/**********************************************************************
 * Base Renderer interface implementation
 **********************************************************************/
TessResultRenderer::TessResultRenderer(const char *outputbase, const char *extension)
    : file_extension_(extension)
    , title_("")
    , imagenum_(-1)
    , fout_(stdout)
    , next_(nullptr)
    , happy_(true) {
  if (strcmp(outputbase, "-") && strcmp(outputbase, "stdout")) {
    std::string outfile = std::string(outputbase) + "." + extension;
    fout_ = fopen(outfile.c_str(), "wb");
    if (fout_ == nullptr) {
      happy_ = false;
    }
  }
}

TessResultRenderer::~TessResultRenderer() {
  if (fout_ != nullptr) {
    if (fout_ != stdout) {
      fclose(fout_);
    } else {
      clearerr(fout_);
    }
  }
  delete next_;
}

void TessResultRenderer::insert(TessResultRenderer *next) {
  if (next == nullptr) {
    return;
  }

  TessResultRenderer *remainder = next_;
  next_ = next;
  if (remainder) {
    while (next->next_ != nullptr) {
      next = next->next_;
    }
    next->next_ = remainder;
  }
}

bool TessResultRenderer::BeginDocument(const char *title) {
  if (!happy_) {
    return false;
  }
  title_ = title;
  imagenum_ = -1;
  bool ok = BeginDocumentHandler();
  if (next_) {
    ok = next_->BeginDocument(title) && ok;
  }
  return ok;
}

bool TessResultRenderer::AddImage(TessBaseAPI *api) {
  if (!happy_) {
    return false;
  }
  ++imagenum_;
  bool ok = AddImageHandler(api);
  if (next_) {
    ok = next_->AddImage(api) && ok;
  }
  return ok;
}

bool TessResultRenderer::EndDocument() {
  if (!happy_) {
    return false;
  }
  bool ok = EndDocumentHandler();
  if (next_) {
    ok = next_->EndDocument() && ok;
  }
  return ok;
}

void TessResultRenderer::AppendString(const char *s) {
  AppendData(s, strlen(s));
}

void TessResultRenderer::AppendData(const char *s, int len) {
  if (!tesseract::Serialize(fout_, s, len)) {
    happy_ = false;
  }
  fflush(fout_);
}

bool TessResultRenderer::BeginDocumentHandler() {
  return happy_;
}

bool TessResultRenderer::EndDocumentHandler() {
  return happy_;
}

/**********************************************************************
 * UTF8 Text Renderer interface implementation
 **********************************************************************/
TessTextRenderer::TessTextRenderer(const char *outputbase)
    : TessResultRenderer(outputbase, "txt") {}

bool TessTextRenderer::AddImageHandler(TessBaseAPI *api) {
  const std::unique_ptr<const char[]> utf8(api->GetUTF8Text());
  if (utf8 == nullptr) {
    return false;
  }

  AppendString(utf8.get());

  const char *pageSeparator = api->GetStringVariable("page_separator");
  if (pageSeparator != nullptr && *pageSeparator != '\0') {
    AppendString(pageSeparator);
  }

  return true;
}

/**********************************************************************
 * TSV Text Renderer interface implementation
 **********************************************************************/
TessTsvRenderer::TessTsvRenderer(const char *outputbase) : TessResultRenderer(outputbase, "tsv") {
  font_info_ = false;
}

TessTsvRenderer::TessTsvRenderer(const char *outputbase, bool font_info)
    : TessResultRenderer(outputbase, "tsv") {
  font_info_ = font_info;
}

bool TessTsvRenderer::BeginDocumentHandler() {
  // Output TSV column headings
  AppendString(
      "level\tpage_num\tblock_num\tpar_num\tline_num\tword_"
      "num\tleft\ttop\twidth\theight\tconf\ttext\n");
  return true;
}

bool TessTsvRenderer::EndDocumentHandler() {
  return true;
}

bool TessTsvRenderer::AddImageHandler(TessBaseAPI *api) {
  const std::unique_ptr<const char[]> tsv(api->GetTSVText(imagenum()));
  if (tsv == nullptr) {
    return false;
  }

  AppendString(tsv.get());

  return true;
}

/**********************************************************************
 * UNLV Text Renderer interface implementation
 **********************************************************************/
TessUnlvRenderer::TessUnlvRenderer(const char *outputbase)
    : TessResultRenderer(outputbase, "unlv") {}

bool TessUnlvRenderer::AddImageHandler(TessBaseAPI *api) {
  const std::unique_ptr<const char[]> unlv(api->GetUNLVText());
  if (unlv == nullptr) {
    return false;
  }

  AppendString(unlv.get());

  return true;
}

/**********************************************************************
 * BoxText Renderer interface implementation
 **********************************************************************/
TessBoxTextRenderer::TessBoxTextRenderer(const char *outputbase)
    : TessResultRenderer(outputbase, "box") {}

bool TessBoxTextRenderer::AddImageHandler(TessBaseAPI *api) {
  const std::unique_ptr<const char[]> text(api->GetBoxText(imagenum()));
  if (text == nullptr) {
    return false;
  }

  AppendString(text.get());

  return true;
}

#ifndef DISABLED_LEGACY_ENGINE

/**********************************************************************
 * Osd Text Renderer interface implementation
 **********************************************************************/
TessOsdRenderer::TessOsdRenderer(const char *outputbase) : TessResultRenderer(outputbase, "osd") {}

bool TessOsdRenderer::AddImageHandler(TessBaseAPI *api) {
  char *osd = api->GetOsdText(imagenum());
  if (osd == nullptr) {
    return false;
  }

  AppendString(osd);
  delete[] osd;

  return true;
}

#endif // ndef DISABLED_LEGACY_ENGINE

} // namespace tesseract
<commit_msg>Modernize code<commit_after>///////////////////////////////////////////////////////////////////////
// File:        renderer.cpp
// Description: Rendering interface to inject into TessBaseAPI
//
// (C) Copyright 2011, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////

#ifdef HAVE_CONFIG_H
#  include "config_auto.h"
#endif
#include <tesseract/baseapi.h>
#include <tesseract/renderer.h>
#include <cstring>
#include <memory>     // std::unique_ptr
#include <string>     // std::string
#include "serialis.h" // Serialize

namespace tesseract {

/**********************************************************************
 * Base Renderer interface implementation
 **********************************************************************/
TessResultRenderer::TessResultRenderer(const char *outputbase, const char *extension)
    : file_extension_(extension)
    , title_("")
    , imagenum_(-1)
    , fout_(stdout)
    , next_(nullptr)
    , happy_(true) {
  if (strcmp(outputbase, "-") && strcmp(outputbase, "stdout")) {
    std::string outfile = std::string(outputbase) + "." + extension;
    fout_ = fopen(outfile.c_str(), "wb");
    if (fout_ == nullptr) {
      happy_ = false;
    }
  }
}

TessResultRenderer::~TessResultRenderer() {
  if (fout_ != nullptr) {
    if (fout_ != stdout) {
      fclose(fout_);
    } else {
      clearerr(fout_);
    }
  }
  delete next_;
}

void TessResultRenderer::insert(TessResultRenderer *next) {
  if (next == nullptr) {
    return;
  }

  TessResultRenderer *remainder = next_;
  next_ = next;
  if (remainder) {
    while (next->next_ != nullptr) {
      next = next->next_;
    }
    next->next_ = remainder;
  }
}

bool TessResultRenderer::BeginDocument(const char *title) {
  if (!happy_) {
    return false;
  }
  title_ = title;
  imagenum_ = -1;
  bool ok = BeginDocumentHandler();
  if (next_) {
    ok = next_->BeginDocument(title) && ok;
  }
  return ok;
}

bool TessResultRenderer::AddImage(TessBaseAPI *api) {
  if (!happy_) {
    return false;
  }
  ++imagenum_;
  bool ok = AddImageHandler(api);
  if (next_) {
    ok = next_->AddImage(api) && ok;
  }
  return ok;
}

bool TessResultRenderer::EndDocument() {
  if (!happy_) {
    return false;
  }
  bool ok = EndDocumentHandler();
  if (next_) {
    ok = next_->EndDocument() && ok;
  }
  return ok;
}

void TessResultRenderer::AppendString(const char *s) {
  AppendData(s, strlen(s));
}

void TessResultRenderer::AppendData(const char *s, int len) {
  if (!tesseract::Serialize(fout_, s, len)) {
    happy_ = false;
  }
  fflush(fout_);
}

bool TessResultRenderer::BeginDocumentHandler() {
  return happy_;
}

bool TessResultRenderer::EndDocumentHandler() {
  return happy_;
}

/**********************************************************************
 * UTF8 Text Renderer interface implementation
 **********************************************************************/
TessTextRenderer::TessTextRenderer(const char *outputbase)
    : TessResultRenderer(outputbase, "txt") {}

bool TessTextRenderer::AddImageHandler(TessBaseAPI *api) {
  const std::unique_ptr<const char[]> utf8(api->GetUTF8Text());
  if (utf8 == nullptr) {
    return false;
  }

  AppendString(utf8.get());

  const char *pageSeparator = api->GetStringVariable("page_separator");
  if (pageSeparator != nullptr && *pageSeparator != '\0') {
    AppendString(pageSeparator);
  }

  return true;
}

/**********************************************************************
 * TSV Text Renderer interface implementation
 **********************************************************************/
TessTsvRenderer::TessTsvRenderer(const char *outputbase) : TessResultRenderer(outputbase, "tsv") {
  font_info_ = false;
}

TessTsvRenderer::TessTsvRenderer(const char *outputbase, bool font_info)
    : TessResultRenderer(outputbase, "tsv") {
  font_info_ = font_info;
}

bool TessTsvRenderer::BeginDocumentHandler() {
  // Output TSV column headings
  AppendString(
      "level\tpage_num\tblock_num\tpar_num\tline_num\tword_"
      "num\tleft\ttop\twidth\theight\tconf\ttext\n");
  return true;
}

bool TessTsvRenderer::EndDocumentHandler() {
  return true;
}

bool TessTsvRenderer::AddImageHandler(TessBaseAPI *api) {
  const std::unique_ptr<const char[]> tsv(api->GetTSVText(imagenum()));
  if (tsv == nullptr) {
    return false;
  }

  AppendString(tsv.get());

  return true;
}

/**********************************************************************
 * UNLV Text Renderer interface implementation
 **********************************************************************/
TessUnlvRenderer::TessUnlvRenderer(const char *outputbase)
    : TessResultRenderer(outputbase, "unlv") {}

bool TessUnlvRenderer::AddImageHandler(TessBaseAPI *api) {
  const std::unique_ptr<const char[]> unlv(api->GetUNLVText());
  if (unlv == nullptr) {
    return false;
  }

  AppendString(unlv.get());

  return true;
}

/**********************************************************************
 * BoxText Renderer interface implementation
 **********************************************************************/
TessBoxTextRenderer::TessBoxTextRenderer(const char *outputbase)
    : TessResultRenderer(outputbase, "box") {}

bool TessBoxTextRenderer::AddImageHandler(TessBaseAPI *api) {
  const std::unique_ptr<const char[]> text(api->GetBoxText(imagenum()));
  if (text == nullptr) {
    return false;
  }

  AppendString(text.get());

  return true;
}

#ifndef DISABLED_LEGACY_ENGINE

/**********************************************************************
 * Osd Text Renderer interface implementation
 **********************************************************************/
TessOsdRenderer::TessOsdRenderer(const char *outputbase) : TessResultRenderer(outputbase, "osd") {}

bool TessOsdRenderer::AddImageHandler(TessBaseAPI *api) {
  const std::unique_ptr<const char[]> osd(api->GetOsdText(imagenum()));
  if (osd == nullptr) {
    return false;
  }

  AppendString(osd.get());

  return true;
}

#endif // ndef DISABLED_LEGACY_ENGINE

} // namespace tesseract
<|endoftext|>


<commit_before>#include <iostream>

int main() {
  std::cout << "cout" << std::endl;
  std::cerr << "cerr" << std::endl;
  std::clog << "clog" << std::endl;

  return 0;
}
<commit_msg>again<commit_after>#include <iostream>

int main() {
  std::cout << "cout" << std::endl;
  std::cerr << "cerr" << std::endl;
  std::clog << "clog" << std::endl;

  try {
    throw std::runtime_error("error");
  } catch(std::runtime_error& e) {
    std::clog << e.what() << std::endl;;
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
 *  libjdksmidi-2004 C++ Class Library for MIDI
 *
 *  Copyright (C) 2004  J.D. Koftinoff Software, Ltd.
 *  www.jdkoftinoff.com
 *  jeffk@jdkoftinoff.com
 *
 *  *** RELEASED UNDER THE GNU GENERAL PUBLIC LICENSE (GPL) April 27, 2004 ***
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  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 General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
//
// Copyright (C) 2010 V.R.Madgazin
// www.vmgames.com vrm@vmgames.com
//

#ifdef WIN32
#include <windows.h>
#endif

#include "jdksmidi/world.h"
#include "jdksmidi/track.h"
#include "jdksmidi/multitrack.h"
#include "jdksmidi/filereadmultitrack.h"
#include "jdksmidi/fileread.h"
#include "jdksmidi/fileshow.h"

using namespace jdksmidi;

void DumpMIDITimedBigMessage ( MIDITimedBigMessage *msg )
{
    if ( msg )
    {
        char msgbuf[1024];
        fprintf ( stdout, "%8ld : %s\n", msg->GetTime(), msg->MsgToText ( msgbuf ) );

        if ( msg->IsSystemExclusive() )
        {
            fprintf ( stdout, "\tSYSEX length: %d\n", msg->GetSysEx()->GetLength() );
        }
    }
}

void DumpMIDITrack ( MIDITrack *t )
{
    MIDITimedBigMessage *msg;

    for ( int i = 0; i < t->GetNumEvents(); ++i )
    {
        msg = t->GetEventAddress ( i );
        DumpMIDITimedBigMessage ( msg );
    }
}

void DumpAllTracks ( MIDIMultiTrack *mlt )
{
    fprintf ( stdout , "Clocks per beat: %d\n\n", mlt->GetClksPerBeat() );

    for ( int i = 0; i < mlt->GetNumTracks(); ++i )
    {
        if ( mlt->GetTrack ( i )->GetNumEvents() > 0 )
        {
            fprintf ( stdout, "DUMP OF TRACK #%2d:\n", i );
            DumpMIDITrack ( mlt->GetTrack ( i ) );
            fprintf ( stdout, "\n" );
        }
    }
}

void DumpMIDIMultiTrack ( MIDIMultiTrack *mlt )
{
    MIDIMultiTrackIterator i ( mlt );
    MIDITimedBigMessage *msg;
    fprintf ( stdout , "Clocks per beat: %d\n\n", mlt->GetClksPerBeat() );
    i.GoToTime ( 0 );

    do
    {
        int trk_num;

        if ( i.GetCurEvent ( &trk_num, &msg ) )
        {
            fprintf ( stdout, "#%2d - ", trk_num );
            DumpMIDITimedBigMessage ( msg );
        }
    }
    while ( i.GoToNextEvent() );
}

int main ( int argc, char **argv )
{
    if ( argc > 1 )
    {
        MIDIFileReadStreamFile rs ( argv[1] );
        MIDIMultiTrack tracks;
        MIDIFileReadMultiTrack track_loader ( &tracks );
        MIDIFileRead reader ( &rs, &track_loader );
        reader.Parse();
        DumpMIDIMultiTrack ( &tracks );
    }

    return 0;
}
<commit_msg>fix test multitrack bug<commit_after>/*
 *  libjdksmidi-2004 C++ Class Library for MIDI
 *
 *  Copyright (C) 2004  J.D. Koftinoff Software, Ltd.
 *  www.jdkoftinoff.com
 *  jeffk@jdkoftinoff.com
 *
 *  *** RELEASED UNDER THE GNU GENERAL PUBLIC LICENSE (GPL) April 27, 2004 ***
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  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 General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
//
// Copyright (C) 2010 V.R.Madgazin
// www.vmgames.com vrm@vmgames.com
//

#ifdef WIN32
#include <windows.h>
#endif

#include "jdksmidi/world.h"
#include "jdksmidi/track.h"
#include "jdksmidi/multitrack.h"
#include "jdksmidi/filereadmultitrack.h"
#include "jdksmidi/fileread.h"
#include "jdksmidi/fileshow.h"

using namespace jdksmidi;

void DumpMIDITimedBigMessage ( const MIDITimedBigMessage *msg )
{
    if ( msg )
    {
        char msgbuf[1024];
        fprintf ( stdout, "%8ld : %s\n", msg->GetTime(), msg->MsgToText ( msgbuf ) );

        if ( msg->IsSystemExclusive() )
        {
            fprintf ( stdout, "\tSYSEX length: %d\n", msg->GetSysEx()->GetLength() );
        }
    }
}

void DumpMIDITrack ( MIDITrack *t )
{
    MIDITimedBigMessage *msg;

    for ( int i = 0; i < t->GetNumEvents(); ++i )
    {
        msg = t->GetEventAddress ( i );
        DumpMIDITimedBigMessage ( msg );
    }
}

void DumpAllTracks ( MIDIMultiTrack *mlt )
{
    fprintf ( stdout , "Clocks per beat: %d\n\n", mlt->GetClksPerBeat() );

    for ( int i = 0; i < mlt->GetNumTracks(); ++i )
    {
        if ( mlt->GetTrack ( i )->GetNumEvents() > 0 )
        {
            fprintf ( stdout, "DUMP OF TRACK #%2d:\n", i );
            DumpMIDITrack ( mlt->GetTrack ( i ) );
            fprintf ( stdout, "\n" );
        }
    }
}

void DumpMIDIMultiTrack ( MIDIMultiTrack *mlt )
{
    MIDIMultiTrackIterator i ( mlt );
    const MIDITimedBigMessage *msg;
    fprintf ( stdout , "Clocks per beat: %d\n\n", mlt->GetClksPerBeat() );
    i.GoToTime ( 0 );

    do
    {
        int trk_num;

        if ( i.GetCurEvent ( &trk_num, &msg ) )
        {
            fprintf ( stdout, "#%2d - ", trk_num );
            DumpMIDITimedBigMessage ( msg );
        }
    }
    while ( i.GoToNextEvent() );
}

int main ( int argc, char **argv )
{
    if ( argc > 1 )
    {
        MIDIFileReadStreamFile rs ( argv[1] );
        MIDIMultiTrack tracks;
        MIDIFileReadMultiTrack track_loader ( &tracks );
        MIDIFileRead reader ( &rs, &track_loader );
        reader.Parse();
        DumpMIDIMultiTrack ( &tracks );
    }

    return 0;
}
<|endoftext|>